зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-i to m-c, a=merge
MozReview-Commit-ID: BnSh8kutBaR
This commit is contained in:
Коммит
0111ff534b
|
@ -33,8 +33,7 @@ this.AccessFu = { // jshint ignore:line
|
|||
Utils.init(aWindow);
|
||||
|
||||
try {
|
||||
Services.androidBridge.handleGeckoMessage(
|
||||
{ type: 'Accessibility:Ready' });
|
||||
Services.androidBridge.dispatch('Accessibility:Ready');
|
||||
Services.obs.addObserver(this, 'Accessibility:Settings', false);
|
||||
} catch (x) {
|
||||
// Not on Android
|
||||
|
@ -602,7 +601,6 @@ var Output = {
|
|||
}
|
||||
|
||||
for (let androidEvent of aDetails) {
|
||||
androidEvent.type = 'Accessibility:Event';
|
||||
if (androidEvent.bounds) {
|
||||
androidEvent.bounds = AccessFu.adjustContentBounds(
|
||||
androidEvent.bounds, aBrowser);
|
||||
|
@ -622,7 +620,9 @@ var Output = {
|
|||
androidEvent.brailleOutput);
|
||||
break;
|
||||
}
|
||||
this.androidBridge.handleGeckoMessage(androidEvent);
|
||||
let win = Utils.win;
|
||||
let view = win && win.QueryInterface(Ci.nsIAndroidView);
|
||||
view.dispatch('Accessibility:Event', androidEvent);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -818,8 +818,9 @@ var Input = {
|
|||
|
||||
if (Utils.MozBuildApp == 'mobile/android') {
|
||||
// Return focus to native Android browser chrome.
|
||||
Services.androidBridge.handleGeckoMessage(
|
||||
{ type: 'ToggleChrome:Focus' });
|
||||
let win = Utils.win;
|
||||
let view = win && win.QueryInterface(Ci.nsIAndroidView);
|
||||
view.dispatch('ToggleChrome:Focus');
|
||||
}
|
||||
break;
|
||||
case aEvent.DOM_VK_RETURN:
|
||||
|
|
|
@ -5731,6 +5731,8 @@ nsDocShell::Destroy()
|
|||
NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,
|
||||
"Unexpected item type in docshell");
|
||||
|
||||
AssertOriginAttributesMatchPrivateBrowsing();
|
||||
|
||||
if (!mIsBeingDestroyed) {
|
||||
nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
|
||||
if (serv) {
|
||||
|
@ -14344,6 +14346,7 @@ nsDocShell::SetOriginAttributes(const DocShellOriginAttributes& aAttrs)
|
|||
}
|
||||
|
||||
SetPrivateBrowsing(isPrivate);
|
||||
AssertOriginAttributesMatchPrivateBrowsing();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMIntersectionObserver)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mQueuedEntries)
|
||||
tmp->Disconnect();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMIntersectionObserver)
|
||||
|
@ -185,9 +186,10 @@ DOMIntersectionObserver::Connect()
|
|||
if (mConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
mConnected = true;
|
||||
nsIDocument* document = mOwner->GetExtantDoc();
|
||||
document->AddIntersectionObserver(this);
|
||||
mConnected = true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -101,9 +101,7 @@ protected:
|
|||
class DOMIntersectionObserver final : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
virtual ~DOMIntersectionObserver() {
|
||||
Disconnect();
|
||||
}
|
||||
virtual ~DOMIntersectionObserver() { }
|
||||
|
||||
public:
|
||||
DOMIntersectionObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,
|
||||
|
|
|
@ -3869,7 +3869,7 @@ Element::ClearDataset()
|
|||
slots->mDataset = nullptr;
|
||||
}
|
||||
|
||||
nsTArray<Element::nsDOMSlots::IntersectionObserverRegistration>*
|
||||
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>*
|
||||
Element::RegisteredIntersectionObservers()
|
||||
{
|
||||
nsDOMSlots* slots = DOMSlots();
|
||||
|
@ -3879,34 +3879,34 @@ Element::RegisteredIntersectionObservers()
|
|||
void
|
||||
Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
|
||||
{
|
||||
RegisteredIntersectionObservers()->AppendElement(
|
||||
nsDOMSlots::IntersectionObserverRegistration { aObserver, -1 });
|
||||
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
|
||||
RegisteredIntersectionObservers();
|
||||
if (observers->Contains(aObserver)) {
|
||||
return;
|
||||
}
|
||||
RegisteredIntersectionObservers()->Put(aObserver, -1);
|
||||
}
|
||||
|
||||
void
|
||||
Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
|
||||
{
|
||||
nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers =
|
||||
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
|
||||
RegisteredIntersectionObservers();
|
||||
for (uint32_t i = 0; i < observers->Length(); ++i) {
|
||||
nsDOMSlots::IntersectionObserverRegistration reg = observers->ElementAt(i);
|
||||
if (reg.observer == aObserver) {
|
||||
observers->RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
observers->Remove(aObserver);
|
||||
}
|
||||
|
||||
bool
|
||||
Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold)
|
||||
{
|
||||
nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers =
|
||||
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
|
||||
RegisteredIntersectionObservers();
|
||||
for (auto& reg : *observers) {
|
||||
if (reg.observer == aObserver && reg.previousThreshold != aThreshold) {
|
||||
reg.previousThreshold = aThreshold;
|
||||
return true;
|
||||
}
|
||||
if (!observers->Contains(aObserver)) {
|
||||
return false;
|
||||
}
|
||||
int32_t previousThreshold = observers->Get(aObserver);
|
||||
if (previousThreshold != aThreshold) {
|
||||
observers->Put(aObserver, aThreshold);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1423,7 +1423,7 @@ protected:
|
|||
nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
|
||||
const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
|
||||
|
||||
nsTArray<nsDOMSlots::IntersectionObserverRegistration>* RegisteredIntersectionObservers();
|
||||
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* RegisteredIntersectionObservers();
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "nsIWeakReference.h" // base class
|
||||
#include "nsNodeUtils.h" // class member nsNodeUtils::CloneNodeImpl
|
||||
#include "nsIHTMLCollection.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
class ContentUnbinder;
|
||||
class nsContentList;
|
||||
|
@ -347,12 +348,7 @@ public:
|
|||
/**
|
||||
* Registered Intersection Observers on the element.
|
||||
*/
|
||||
struct IntersectionObserverRegistration {
|
||||
DOMIntersectionObserver* observer;
|
||||
int32_t previousThreshold;
|
||||
};
|
||||
|
||||
nsTArray<IntersectionObserverRegistration> mRegisteredIntersectionObservers;
|
||||
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t> mRegisteredIntersectionObservers;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
@ -301,8 +301,9 @@ nsNodeUtils::LastRelease(nsINode* aNode)
|
|||
Element* elem = aNode->AsElement();
|
||||
FragmentOrElement::nsDOMSlots* domSlots =
|
||||
static_cast<FragmentOrElement::nsDOMSlots*>(slots);
|
||||
for (auto& reg : domSlots->mRegisteredIntersectionObservers) {
|
||||
reg.observer->UnlinkTarget(*elem);
|
||||
for (auto iter = domSlots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
|
||||
DOMIntersectionObserver* observer = iter.Key();
|
||||
observer->UnlinkTarget(*elem);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -891,6 +891,19 @@ limitations under the License.
|
|||
var win = window.open("intersectionobserver_window.html");
|
||||
});
|
||||
|
||||
it('triggers only once if observed multiple times (and does not crash when collected)', function(done) {
|
||||
var spy = sinon.spy();
|
||||
io = new IntersectionObserver(spy, {root: rootEl});
|
||||
io.observe(targetEl1);
|
||||
io.observe(targetEl1);
|
||||
io.observe(targetEl1);
|
||||
|
||||
callDelayed(function () {
|
||||
expect(spy.callCount).to.be(1);
|
||||
done();
|
||||
}, ASYNC_TIMEOUT);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('observe subframe', function () {
|
||||
|
|
|
@ -35,18 +35,95 @@ function turnOnPointerEvents(callback) {
|
|||
}, callback);
|
||||
}
|
||||
|
||||
// Mouse Event Helper Object
|
||||
var MouseEventHelper = (function() {
|
||||
var utils = SpecialPowers.Ci.nsIDOMWindowUtils;
|
||||
|
||||
return {
|
||||
// State
|
||||
// TODO: Separate this to support mouse and pen simultaneously.
|
||||
BUTTONS_STATE: utils.MOUSE_BUTTONS_NO_BUTTON,
|
||||
|
||||
// Button
|
||||
BUTTON_NONE: -1, // Used by test framework only. (replaced before sending)
|
||||
BUTTON_LEFT: utils.MOUSE_BUTTON_LEFT_BUTTON,
|
||||
BUTTON_MIDDLE: utils.MOUSE_BUTTON_MIDDLE_BUTTON,
|
||||
BUTTON_RIGHT: utils.MOUSE_BUTTON_RIGHT_BUTTON,
|
||||
|
||||
// Buttons
|
||||
BUTTONS_NONE: utils.MOUSE_BUTTONS_NO_BUTTON,
|
||||
BUTTONS_LEFT: utils.MOUSE_BUTTONS_LEFT_BUTTON,
|
||||
BUTTONS_MIDDLE: utils.MOUSE_BUTTONS_MIDDLE_BUTTON,
|
||||
BUTTONS_RIGHT: utils.MOUSE_BUTTONS_RIGHT_BUTTON,
|
||||
BUTTONS_4TH: utils.MOUSE_BUTTONS_4TH_BUTTON,
|
||||
BUTTONS_5TH: utils.MOUSE_BUTTONS_5TH_BUTTON,
|
||||
|
||||
// Utils
|
||||
computeButtonsMaskFromButton: function(aButton) {
|
||||
// Since the range of button values is 0 ~ 2 (see nsIDOMWindowUtils.idl),
|
||||
// we can use an array to find out the desired mask.
|
||||
var mask = [
|
||||
this.BUTTONS_NONE, // -1 (MouseEventHelper.BUTTON_NONE)
|
||||
this.BUTTONS_LEFT, // 0
|
||||
this.BUTTONS_MIDDLE, // 1
|
||||
this.BUTTONS_RIGHT // 2
|
||||
][aButton + 1];
|
||||
|
||||
ok(mask !== undefined, "Unrecognized button value caught!");
|
||||
return mask;
|
||||
},
|
||||
|
||||
checkExitState: function() {
|
||||
ok(!this.BUTTONS_STATE, "Mismatched mousedown/mouseup caught.");
|
||||
}
|
||||
};
|
||||
}) ();
|
||||
|
||||
// Helper function to send MouseEvent with different parameters
|
||||
function sendMouseEvent(int_win, elemId, mouseEventType, params) {
|
||||
var elem = int_win.document.getElementById(elemId);
|
||||
if(!!elem) {
|
||||
var rect = elem.getBoundingClientRect();
|
||||
var eventObj = {type: mouseEventType};
|
||||
if(params && "button" in params)
|
||||
eventObj.button = params.button;
|
||||
|
||||
if(params && "inputSource" in params)
|
||||
eventObj.inputSource = params.inputSource;
|
||||
if(params && "buttons" in params)
|
||||
eventObj.buttons = params.buttons;
|
||||
|
||||
// Check or generate a |button| value.
|
||||
var isButtonEvent = mouseEventType === "mouseup" ||
|
||||
mouseEventType === "mousedown";
|
||||
|
||||
// Set |button| to the default value first.
|
||||
eventObj.button = isButtonEvent ? MouseEventHelper.BUTTON_LEFT
|
||||
: MouseEventHelper.BUTTON_NONE;
|
||||
|
||||
// |button| is passed, use and check it.
|
||||
if (params && "button" in params) {
|
||||
var hasButtonValue = (params.button !== MouseEventHelper.BUTTON_NONE);
|
||||
ok(!isButtonEvent || hasButtonValue,
|
||||
"Inappropriate |button| value caught.");
|
||||
eventObj.button = params.button;
|
||||
}
|
||||
|
||||
// Generate a |buttons| value and update buttons state
|
||||
var buttonsMask = MouseEventHelper.computeButtonsMaskFromButton(eventObj.button);
|
||||
switch(mouseEventType) {
|
||||
case "mousedown":
|
||||
MouseEventHelper.BUTTONS_STATE |= buttonsMask; // Set button flag.
|
||||
break;
|
||||
case "mouseup":
|
||||
MouseEventHelper.BUTTONS_STATE &= ~buttonsMask; // Clear button flag.
|
||||
break;
|
||||
}
|
||||
eventObj.buttons = MouseEventHelper.BUTTONS_STATE;
|
||||
|
||||
// Replace the button value for mousemove events.
|
||||
// Since in widget level design, even when no button is pressed at all, the
|
||||
// value of WidgetMouseEvent.button is still 0, which is the same value as
|
||||
// the one for mouse left button.
|
||||
if (mouseEventType === "mousemove") {
|
||||
eventObj.button = MouseEventHelper.BUTTON_LEFT;
|
||||
}
|
||||
|
||||
// Default to the center of the target element but we can still send to a
|
||||
// position outside of the target element.
|
||||
|
@ -61,6 +138,18 @@ function sendMouseEvent(int_win, elemId, mouseEventType, params) {
|
|||
}
|
||||
}
|
||||
|
||||
// Touch Event Helper Object
|
||||
var TouchEventHelper = {
|
||||
// State
|
||||
// TODO: Support multiple point scenarios.
|
||||
TOUCH_STATE: false,
|
||||
|
||||
// Utils
|
||||
checkExitState: function() {
|
||||
ok(!this.TOUCH_STATE, "Mismatched touchstart/touchend caught.");
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to send TouchEvent with different parameters
|
||||
function sendTouchEvent(int_win, elemId, touchEventType, params) {
|
||||
var elem = int_win.document.getElementById(elemId);
|
||||
|
@ -68,6 +157,16 @@ function sendTouchEvent(int_win, elemId, touchEventType, params) {
|
|||
var rect = elem.getBoundingClientRect();
|
||||
var eventObj = {type: touchEventType};
|
||||
|
||||
// Update touch state
|
||||
switch(touchEventType) {
|
||||
case "touchstart":
|
||||
TouchEventHelper.TOUCH_STATE = true; // Set touch flag.
|
||||
break;
|
||||
case "touchend":
|
||||
TouchEventHelper.TOUCH_STATE = false; // Clear touch flag.
|
||||
break;
|
||||
}
|
||||
|
||||
// Default to the center of the target element but we can still send to a
|
||||
// position outside of the target element.
|
||||
var offsetX = params && "offsetX" in params ? params.offsetX : rect.width / 2;
|
||||
|
@ -82,42 +181,25 @@ function sendTouchEvent(int_win, elemId, touchEventType, params) {
|
|||
|
||||
// Helper function to run Point Event test in a new tab.
|
||||
function runTestInNewWindow(aFile) {
|
||||
var w = window.open('', "_blank");
|
||||
w.is = function(a, b, msg) { return is(a, b, aFile + " | " + msg); };
|
||||
w.ok = function(cond, name, diag) { return ok(cond, aFile + " | " + name, diag); };
|
||||
w.location = location.href.substring(0, location.href.lastIndexOf('/') + 1) + aFile;
|
||||
var testURL = location.href.substring(0, location.href.lastIndexOf('/') + 1) + aFile;
|
||||
var testWindow = window.open(testURL, "_blank");
|
||||
|
||||
w.testContext = {
|
||||
result_callback: (aTestObj) => {
|
||||
if(aTestObj["status"] != aTestObj["PASS"]) {
|
||||
console.log(aTestObj["status"] + " = " + aTestObj["PASS"] + ". " + aTestObj["name"]);
|
||||
}
|
||||
is(aTestObj["status"], aTestObj["PASS"], aTestObj["name"]);
|
||||
},
|
||||
|
||||
completion_callback: () => {
|
||||
if (!!w.testContext.executionPromise) {
|
||||
// We need to wait tests done and execute finished then we can close the window
|
||||
w.testContext.executionPromise.then(() => {
|
||||
w.close();
|
||||
SimpleTest.finish();
|
||||
window.addEventListener("message", function(aEvent) {
|
||||
switch(aEvent.data.type) {
|
||||
case "START":
|
||||
turnOnPointerEvents(() => {
|
||||
executeTest(testWindow);
|
||||
});
|
||||
} else {
|
||||
// execute may synchronous trigger tests done. In that case executionPromise
|
||||
// is not yet assigned
|
||||
w.close();
|
||||
return;
|
||||
case "RESULT":
|
||||
ok(aEvent.data.result, aEvent.data.message);
|
||||
return;
|
||||
case "FIN":
|
||||
MouseEventHelper.checkExitState();
|
||||
TouchEventHelper.checkExitState();
|
||||
testWindow.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
},
|
||||
|
||||
execute: (aWindow) => {
|
||||
turnOnPointerEvents(() => {
|
||||
w.testContext.executionPromise = new Promise((aResolve, aReject) => {
|
||||
executeTest(aWindow);
|
||||
aResolve();
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
return w;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,21 +2,34 @@
|
|||
// to tests on auto MochiTest system with minimum changes.
|
||||
// Author: Maksim Lebedev <alessarik@gmail.com>
|
||||
|
||||
// Function allows to prepare our tests after load document
|
||||
addEventListener("load", function(event) {
|
||||
const PARENT_ORIGIN = "http://mochi.test:8888/";
|
||||
|
||||
addEventListener("load", function() {
|
||||
// Setup environment.
|
||||
console.log("OnLoad internal document");
|
||||
addListeners(document.getElementById("target0"));
|
||||
addListeners(document.getElementById("target1"));
|
||||
preExecute();
|
||||
}, false);
|
||||
|
||||
// Function allows to initialize prerequisites before testing
|
||||
// and adds some callbacks to support mochitest system.
|
||||
function preExecute() {
|
||||
add_result_callback(testContext.result_callback);
|
||||
add_completion_callback(testContext.completion_callback);
|
||||
testContext.execute(window);
|
||||
}
|
||||
// Setup communication between mochitest_support_external.js.
|
||||
// Function allows to initialize prerequisites before testing
|
||||
// and adds some callbacks to support mochitest system.
|
||||
add_result_callback((aTestObj) => {
|
||||
var message = aTestObj["name"] + " (";
|
||||
message += "Get: " + JSON.stringify(aTestObj["status"]) + ", ";
|
||||
message += "Expect: " + JSON.stringify(aTestObj["PASS"]) + ")";
|
||||
window.opener.postMessage({type: "RESULT",
|
||||
message: message,
|
||||
result: aTestObj["status"] === aTestObj["PASS"]},
|
||||
PARENT_ORIGIN);
|
||||
});
|
||||
|
||||
add_completion_callback(() => {
|
||||
window.opener.postMessage({type: "FIN"}, PARENT_ORIGIN);
|
||||
});
|
||||
|
||||
// Start testing.
|
||||
window.opener.postMessage({type: "START"}, PARENT_ORIGIN);
|
||||
});
|
||||
|
||||
function addListeners(elem) {
|
||||
if(!elem)
|
||||
|
|
|
@ -17,13 +17,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
runTestInNewWindow("pointerevent_attributes_mouse-manual.html");
|
||||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "square1", "mousemove", {button:-1});
|
||||
sendMouseEvent(int_win, "square1", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "square1", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "square1", "mousemove", {button:-1});
|
||||
sendMouseEvent(int_win, "square1", "mousemove", {button:-1,
|
||||
offsetX: -1,
|
||||
offsetY: -1});
|
||||
sendMouseEvent(int_win, "square1", "mousemove");
|
||||
sendMouseEvent(int_win, "square1", "mousedown");
|
||||
sendMouseEvent(int_win, "square1", "mouseup");
|
||||
sendMouseEvent(int_win, "square1", "mousemove");
|
||||
sendMouseEvent(int_win, "square1", "mousemove", {offsetX: -1, offSetY: -1});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
sendMouseEvent(int_win, "btnCapture", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
sendMouseEvent(int_win, "btnCapture", "mousedown", {button:1});
|
||||
sendMouseEvent(int_win, "btnCapture", "mousedown");
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mouseup");
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
|
|
|
@ -19,7 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
sendMouseEvent(int_win, "btnCapture", "mousedown", {button:1});
|
||||
sendMouseEvent(int_win, "btnCapture", "mousedown");
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
|
|
|
@ -18,12 +18,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mouseup");
|
||||
sendMouseEvent(int_win, "target1", "mousedown");
|
||||
sendMouseEvent(int_win, "target1", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -18,10 +18,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -17,8 +17,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
runTestInNewWindow("pointerevent_gotpointercapture_before_first_pointerevent-manual.html");
|
||||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -22,6 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
sendMouseEvent(int_win, "btnCapture", "mousemove");
|
||||
setTimeout(function() {
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mouseup");
|
||||
}, 500);
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -17,8 +17,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
runTestInNewWindow("pointerevent_lostpointercapture_is_first-manual.html");
|
||||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "btnCapture", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "btnCapture", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "btnCapture", "mousedown");
|
||||
sendMouseEvent(int_win, "btnCapture", "mouseup");
|
||||
sendMouseEvent(int_win, "btnCapture", "mousemove");
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -21,8 +21,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
sendTouchEvent(int_win, "target1", "touchstart");
|
||||
sendTouchEvent(int_win, "target1", "touchend");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "done", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "done", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "done", "mousedown");
|
||||
sendMouseEvent(int_win, "done", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
function executeTest(int_win) {
|
||||
sendTouchEvent(int_win, "target0", "touchstart");
|
||||
sendTouchEvent(int_win, "target0", "touchcancel");
|
||||
|
||||
// Need a touchend event to terminated the test gracefully.
|
||||
sendTouchEvent(int_win, "target0", "touchend");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -18,7 +18,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "log", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:1});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -18,6 +18,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
function executeTest(int_win) {
|
||||
sendTouchEvent(int_win, "target0", "touchstart");
|
||||
sendTouchEvent(int_win, "target0", "touchcancel");
|
||||
|
||||
// Need a touchend event to terminated the test gracefully.
|
||||
sendTouchEvent(int_win, "target0", "touchend");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -18,17 +18,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
}
|
||||
|
||||
function executeTest(int_win) {
|
||||
var utils = _getDOMWindowUtils(int_win);
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0, buttons:utils.MOUSE_BUTTONS_NO_BUTTON});
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON |
|
||||
utils.MOUSE_BUTTONS_MIDDLE_BUTTON});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON |
|
||||
utils.MOUSE_BUTTONS_MIDDLE_BUTTON});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:0, buttons:utils.MOUSE_BUTTONS_NO_BUTTON});
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button: MouseEventHelper.BUTTON_LEFT});
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button: MouseEventHelper.BUTTON_MIDDLE});
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button: MouseEventHelper.BUTTON_MIDDLE});
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button: MouseEventHelper.BUTTON_LEFT});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -19,6 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
function executeTest(int_win) {
|
||||
sendTouchEvent(int_win, "target0", "touchstart");
|
||||
sendTouchEvent(int_win, "target0", "touchcancel");
|
||||
|
||||
// Need a touchend event to terminated the test gracefully.
|
||||
sendTouchEvent(int_win, "target0", "touchend");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -17,8 +17,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
runTestInNewWindow("pointerevent_pointertype_mouse-manual.html");
|
||||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -17,8 +17,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
runTestInNewWindow("pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html");
|
||||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
function executeTest(int_win) {
|
||||
sendTouchEvent(int_win, "target0", "touchstart");
|
||||
sendTouchEvent(int_win, "target0", "touchmove");
|
||||
|
||||
// Need a touchend event to terminated the test gracefully.
|
||||
sendTouchEvent(int_win, "target0", "touchend");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
function executeTest(int_win) {
|
||||
sendTouchEvent(int_win, "target0", "touchstart");
|
||||
sendTouchEvent(int_win, "target0", "touchcancel");
|
||||
|
||||
// Need a touchend event to terminated the test gracefully.
|
||||
sendTouchEvent(int_win, "target0", "touchend");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -17,11 +17,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -18,6 +18,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -18,11 +18,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -18,11 +18,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -17,12 +17,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
runTestInNewWindow("pointerevent_suppress_compat_events_on_click.html");
|
||||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "done", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "done", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
sendMouseEvent(int_win, "target1", "mousedown");
|
||||
sendMouseEvent(int_win, "target1", "mouseup");
|
||||
sendMouseEvent(int_win, "done", "mousedown");
|
||||
sendMouseEvent(int_win, "done", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -17,14 +17,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
|
|||
runTestInNewWindow("pointerevent_suppress_compat_events_on_drag_mouse.html");
|
||||
}
|
||||
function executeTest(int_win) {
|
||||
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mousemove", {button:0});
|
||||
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "done", "mousedown", {button:0});
|
||||
sendMouseEvent(int_win, "done", "mouseup", {button:0});
|
||||
sendMouseEvent(int_win, "target0", "mousedown");
|
||||
sendMouseEvent(int_win, "target0", "mousemove");
|
||||
sendMouseEvent(int_win, "target0", "mouseup");
|
||||
sendMouseEvent(int_win, "target1", "mousedown");
|
||||
sendMouseEvent(int_win, "target1", "mousemove");
|
||||
sendMouseEvent(int_win, "target1", "mouseup");
|
||||
sendMouseEvent(int_win, "done", "mousedown");
|
||||
sendMouseEvent(int_win, "done", "mouseup");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -1973,6 +1973,12 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
*/
|
||||
readonly attribute int32_t gpuProcessPid;
|
||||
|
||||
// Match WidgetMouseEventBase::buttonType.
|
||||
const long MOUSE_BUTTON_LEFT_BUTTON = 0;
|
||||
const long MOUSE_BUTTON_MIDDLE_BUTTON = 1;
|
||||
const long MOUSE_BUTTON_RIGHT_BUTTON = 2;
|
||||
|
||||
// Match WidgetMouseEventBase::buttonsFlag.
|
||||
const long MOUSE_BUTTONS_NO_BUTTON = 0x00;
|
||||
const long MOUSE_BUTTONS_LEFT_BUTTON = 0x01;
|
||||
const long MOUSE_BUTTONS_RIGHT_BUTTON = 0x02;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'mozHunspell.cpp',
|
||||
'mozHunspellDirProvider.cpp',
|
||||
'RemoteSpellCheckEngineChild.cpp',
|
||||
|
|
|
@ -200,7 +200,7 @@ NS_IMETHODIMP mozHunspell::SetDictionary(const char16_t *aDictionary)
|
|||
if (!mHunspell)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsDependentCString label(mHunspell->get_dic_encoding());
|
||||
nsAutoCString label(mHunspell->get_dict_encoding().c_str());
|
||||
nsAutoCString encoding;
|
||||
if (!EncodingUtils::FindEncodingForLabelNoReplacement(label, encoding)) {
|
||||
return NS_ERROR_UCONV_NOCONV;
|
||||
|
@ -480,7 +480,8 @@ mozHunspell::LoadDictionariesFromDir(nsIFile* aDir)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult mozHunspell::ConvertCharset(const char16_t* aStr, char ** aDst)
|
||||
nsresult
|
||||
mozHunspell::ConvertCharset(const char16_t* aStr, std::string* aDst)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDst);
|
||||
NS_ENSURE_TRUE(mEncoder, NS_ERROR_NULL_POINTER);
|
||||
|
@ -490,12 +491,13 @@ nsresult mozHunspell::ConvertCharset(const char16_t* aStr, char ** aDst)
|
|||
nsresult rv = mEncoder->GetMaxLength(aStr, inLength, &outLength);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aDst = (char *) moz_xmalloc(sizeof(char) * (outLength+1));
|
||||
NS_ENSURE_TRUE(*aDst, NS_ERROR_OUT_OF_MEMORY);
|
||||
aDst->resize(outLength);
|
||||
|
||||
rv = mEncoder->Convert(aStr, &inLength, *aDst, &outLength);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
(*aDst)[outLength] = '\0';
|
||||
char* dst = &aDst->operator[](0);
|
||||
rv = mEncoder->Convert(aStr, &inLength, dst, &outLength);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aDst->resize(outLength);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -518,12 +520,11 @@ NS_IMETHODIMP mozHunspell::Check(const char16_t *aWord, bool *aResult)
|
|||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE);
|
||||
|
||||
nsXPIDLCString charsetWord;
|
||||
nsresult rv = ConvertCharset(aWord, getter_Copies(charsetWord));
|
||||
std::string charsetWord;
|
||||
nsresult rv = ConvertCharset(aWord, &charsetWord);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aResult = !!mHunspell->spell(charsetWord);
|
||||
|
||||
*aResult = mHunspell->spell(charsetWord);
|
||||
|
||||
if (!*aResult && mPersonalDictionary)
|
||||
rv = mPersonalDictionary->Check(aWord, mLanguage.get(), aResult);
|
||||
|
@ -540,12 +541,12 @@ NS_IMETHODIMP mozHunspell::Suggest(const char16_t *aWord, char16_t ***aSuggestio
|
|||
nsresult rv;
|
||||
*aSuggestionCount = 0;
|
||||
|
||||
nsXPIDLCString charsetWord;
|
||||
rv = ConvertCharset(aWord, getter_Copies(charsetWord));
|
||||
std::string charsetWord;
|
||||
rv = ConvertCharset(aWord, &charsetWord);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
char ** wlst;
|
||||
*aSuggestionCount = mHunspell->suggest(&wlst, charsetWord);
|
||||
std::vector<std::string> suggestions = mHunspell->suggest(charsetWord);
|
||||
*aSuggestionCount = static_cast<uint32_t>(suggestions.size());
|
||||
|
||||
if (*aSuggestionCount) {
|
||||
*aSuggestions = (char16_t **)moz_xmalloc(*aSuggestionCount * sizeof(char16_t *));
|
||||
|
@ -553,15 +554,15 @@ NS_IMETHODIMP mozHunspell::Suggest(const char16_t *aWord, char16_t ***aSuggestio
|
|||
uint32_t index = 0;
|
||||
for (index = 0; index < *aSuggestionCount && NS_SUCCEEDED(rv); ++index) {
|
||||
// Convert the suggestion to utf16
|
||||
int32_t inLength = strlen(wlst[index]);
|
||||
int32_t inLength = suggestions[index].size();
|
||||
int32_t outLength;
|
||||
rv = mDecoder->GetMaxLength(wlst[index], inLength, &outLength);
|
||||
rv = mDecoder->GetMaxLength(suggestions[index].c_str(), inLength, &outLength);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
(*aSuggestions)[index] = (char16_t *) moz_xmalloc(sizeof(char16_t) * (outLength+1));
|
||||
if ((*aSuggestions)[index])
|
||||
{
|
||||
rv = mDecoder->Convert(wlst[index], &inLength, (*aSuggestions)[index], &outLength);
|
||||
rv = mDecoder->Convert(suggestions[index].c_str(), &inLength, (*aSuggestions)[index], &outLength);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
(*aSuggestions)[index][outLength] = 0;
|
||||
}
|
||||
|
@ -577,7 +578,6 @@ NS_IMETHODIMP mozHunspell::Suggest(const char16_t *aWord, char16_t ***aSuggestio
|
|||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(*aSuggestionCount, wlst);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
void LoadDictionaryList(bool aNotifyChildProcesses);
|
||||
|
||||
// helper method for converting a word to the charset of the dictionary
|
||||
nsresult ConvertCharset(const char16_t* aStr, char ** aDst);
|
||||
nsresult ConvertCharset(const char16_t* aStr, std::string* aDst);
|
||||
|
||||
NS_DECL_NSIMEMORYREPORTER
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Hunspell Version: 1.4.1
|
||||
Hunspell Version: 1.5.4
|
||||
Additional Patches: See patches directory.
|
||||
|
|
|
@ -79,33 +79,7 @@
|
|||
#include "affentry.hxx"
|
||||
#include "csutil.hxx"
|
||||
|
||||
PfxEntry::PfxEntry(AffixMgr* pmgr, affentry* dp)
|
||||
// register affix manager
|
||||
: pmyMgr(pmgr),
|
||||
next(NULL),
|
||||
nexteq(NULL),
|
||||
nextne(NULL),
|
||||
flgnxt(NULL) {
|
||||
// set up its initial values
|
||||
aflag = dp->aflag; // flag
|
||||
strip = dp->strip; // string to strip
|
||||
appnd = dp->appnd; // string to append
|
||||
numconds = dp->numconds; // length of the condition
|
||||
opts = dp->opts; // cross product flag
|
||||
// then copy over all of the conditions
|
||||
if (opts & aeLONGCOND) {
|
||||
memcpy(c.conds, dp->c.l.conds1, MAXCONDLEN_1);
|
||||
c.l.conds2 = dp->c.l.conds2;
|
||||
} else
|
||||
memcpy(c.conds, dp->c.conds, MAXCONDLEN);
|
||||
morphcode = dp->morphcode;
|
||||
contclass = dp->contclass;
|
||||
contclasslen = dp->contclasslen;
|
||||
}
|
||||
|
||||
PfxEntry::~PfxEntry() {
|
||||
aflag = 0;
|
||||
pmyMgr = NULL;
|
||||
AffEntry::~AffEntry() {
|
||||
if (opts & aeLONGCOND)
|
||||
free(c.l.conds2);
|
||||
if (morphcode && !(opts & aeALIASM))
|
||||
|
@ -114,17 +88,26 @@ PfxEntry::~PfxEntry() {
|
|||
free(contclass);
|
||||
}
|
||||
|
||||
PfxEntry::PfxEntry(AffixMgr* pmgr)
|
||||
// register affix manager
|
||||
: pmyMgr(pmgr),
|
||||
next(NULL),
|
||||
nexteq(NULL),
|
||||
nextne(NULL),
|
||||
flgnxt(NULL) {
|
||||
}
|
||||
|
||||
// add prefix to this word assuming conditions hold
|
||||
char* PfxEntry::add(const char* word, size_t len) {
|
||||
std::string PfxEntry::add(const char* word, size_t len) {
|
||||
std::string result;
|
||||
if ((len > strip.size() || (len == 0 && pmyMgr->get_fullstrip())) &&
|
||||
(len >= numconds) && test_condition(word) &&
|
||||
(!strip.size() || (strncmp(word, strip.c_str(), strip.size()) == 0))) {
|
||||
/* we have a match so add prefix */
|
||||
std::string tword(appnd);
|
||||
tword.append(word + strip.size());
|
||||
return mystrdup(tword.c_str());
|
||||
result.assign(appnd);
|
||||
result.append(word + strip.size());
|
||||
}
|
||||
return NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline char* PfxEntry::nextchar(char* p) {
|
||||
|
@ -276,8 +259,7 @@ struct hentry* PfxEntry::checkword(const char* word,
|
|||
// if ((opts & aeXPRODUCT) && in_compound) {
|
||||
if ((opts & aeXPRODUCT)) {
|
||||
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, aeXPRODUCT, this,
|
||||
NULL, 0, NULL, FLAG_NULL, needflag,
|
||||
in_compound);
|
||||
FLAG_NULL, needflag, in_compound);
|
||||
if (he)
|
||||
return he;
|
||||
}
|
||||
|
@ -291,8 +273,6 @@ struct hentry* PfxEntry::check_twosfx(const char* word,
|
|||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag) {
|
||||
struct hentry* he; // hash entry of root word or NULL
|
||||
|
||||
// on entry prefix is 0 length or already matches the beginning of the word.
|
||||
// So if the remaining root word has positive length
|
||||
// and if there are enough chars in root word and added back strip chars
|
||||
|
@ -324,8 +304,9 @@ struct hentry* PfxEntry::check_twosfx(const char* word,
|
|||
// cross checked combined with a suffix
|
||||
|
||||
if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
|
||||
he = pmyMgr->suffix_check_twosfx(tmpword.c_str(), tmpl, aeXPRODUCT, this,
|
||||
needflag);
|
||||
// hash entry of root word or NULL
|
||||
struct hentry* he = pmyMgr->suffix_check_twosfx(tmpword.c_str(), tmpl, aeXPRODUCT, this,
|
||||
needflag);
|
||||
if (he)
|
||||
return he;
|
||||
}
|
||||
|
@ -335,15 +316,15 @@ struct hentry* PfxEntry::check_twosfx(const char* word,
|
|||
}
|
||||
|
||||
// check if this prefix entry matches
|
||||
char* PfxEntry::check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag) {
|
||||
std::string PfxEntry::check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag) {
|
||||
std::string result;
|
||||
// on entry prefix is 0 length or already matches the beginning of the word.
|
||||
// So if the remaining root word has positive length
|
||||
// and if there are enough chars in root word and added back strip chars
|
||||
// to meet the number of characters conditions, then test it
|
||||
|
||||
int tmpl = len - appnd.size(); // length of tmpword
|
||||
|
||||
if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) &&
|
||||
|
@ -370,22 +351,21 @@ char* PfxEntry::check_twosfx_morph(const char* word,
|
|||
// ross checked combined with a suffix
|
||||
|
||||
if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
|
||||
return pmyMgr->suffix_check_twosfx_morph(tmpword.c_str(), tmpl,
|
||||
aeXPRODUCT,
|
||||
this, needflag);
|
||||
result = pmyMgr->suffix_check_twosfx_morph(tmpword.c_str(), tmpl,
|
||||
aeXPRODUCT,
|
||||
this, needflag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
// check if this prefix entry matches
|
||||
char* PfxEntry::check_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag) {
|
||||
struct hentry* he; // hash entry of root word or NULL
|
||||
char* st;
|
||||
std::string PfxEntry::check_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag) {
|
||||
std::string result;
|
||||
|
||||
// on entry prefix is 0 length or already matches the beginning of the word.
|
||||
// So if the remaining root word has positive length
|
||||
|
@ -411,9 +391,8 @@ char* PfxEntry::check_morph(const char* word,
|
|||
// root word in the dictionary
|
||||
|
||||
if (test_condition(tmpword.c_str())) {
|
||||
std::string result;
|
||||
|
||||
tmpl += strip.size();
|
||||
struct hentry* he; // hash entry of root word or NULL
|
||||
if ((he = pmyMgr->lookup(tmpword.c_str())) != NULL) {
|
||||
do {
|
||||
if (TESTAFF(he->astr, aflag, he->alen) &&
|
||||
|
@ -455,23 +434,19 @@ char* PfxEntry::check_morph(const char* word,
|
|||
// ross checked combined with a suffix
|
||||
|
||||
if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
|
||||
st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, aeXPRODUCT, this,
|
||||
FLAG_NULL, needflag);
|
||||
if (st) {
|
||||
std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, aeXPRODUCT, this,
|
||||
FLAG_NULL, needflag);
|
||||
if (!st.empty()) {
|
||||
result.append(st);
|
||||
free(st);
|
||||
}
|
||||
}
|
||||
|
||||
if (!result.empty())
|
||||
return mystrdup(result.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
SfxEntry::SfxEntry(AffixMgr* pmgr, affentry* dp)
|
||||
SfxEntry::SfxEntry(AffixMgr* pmgr)
|
||||
: pmyMgr(pmgr) // register affix manager
|
||||
,
|
||||
next(NULL),
|
||||
|
@ -481,50 +456,21 @@ SfxEntry::SfxEntry(AffixMgr* pmgr, affentry* dp)
|
|||
l_morph(NULL),
|
||||
r_morph(NULL),
|
||||
eq_morph(NULL) {
|
||||
// set up its initial values
|
||||
aflag = dp->aflag; // char flag
|
||||
strip = dp->strip; // string to strip
|
||||
appnd = dp->appnd; // string to append
|
||||
numconds = dp->numconds; // length of the condition
|
||||
opts = dp->opts; // cross product flag
|
||||
|
||||
// then copy over all of the conditions
|
||||
if (opts & aeLONGCOND) {
|
||||
memcpy(c.l.conds1, dp->c.l.conds1, MAXCONDLEN_1);
|
||||
c.l.conds2 = dp->c.l.conds2;
|
||||
} else
|
||||
memcpy(c.conds, dp->c.conds, MAXCONDLEN);
|
||||
rappnd = appnd;
|
||||
reverseword(rappnd);
|
||||
morphcode = dp->morphcode;
|
||||
contclass = dp->contclass;
|
||||
contclasslen = dp->contclasslen;
|
||||
}
|
||||
|
||||
SfxEntry::~SfxEntry() {
|
||||
aflag = 0;
|
||||
pmyMgr = NULL;
|
||||
if (opts & aeLONGCOND)
|
||||
free(c.l.conds2);
|
||||
if (morphcode && !(opts & aeALIASM))
|
||||
free(morphcode);
|
||||
if (contclass && !(opts & aeALIASF))
|
||||
free(contclass);
|
||||
}
|
||||
|
||||
// add suffix to this word assuming conditions hold
|
||||
char* SfxEntry::add(const char* word, size_t len) {
|
||||
std::string SfxEntry::add(const char* word, size_t len) {
|
||||
std::string result;
|
||||
/* make sure all conditions match */
|
||||
if ((len > strip.size() || (len == 0 && pmyMgr->get_fullstrip())) &&
|
||||
(len >= numconds) && test_condition(word + len, word) &&
|
||||
(!strip.size() ||
|
||||
(strcmp(word + len - strip.size(), strip.c_str()) == 0))) {
|
||||
std::string tword(word);
|
||||
result.assign(word);
|
||||
/* we have a match so add suffix */
|
||||
tword.replace(len - strip.size(), std::string::npos, appnd);
|
||||
return mystrdup(tword.c_str());
|
||||
result.replace(len - strip.size(), std::string::npos, appnd);
|
||||
}
|
||||
return NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline char* SfxEntry::nextchar(char* p) {
|
||||
|
@ -669,9 +615,6 @@ struct hentry* SfxEntry::checkword(const char* word,
|
|||
int len,
|
||||
int optflags,
|
||||
PfxEntry* ppfx,
|
||||
char** wlst,
|
||||
int maxSug,
|
||||
int* ns,
|
||||
const FLAG cclass,
|
||||
const FLAG needflag,
|
||||
const FLAG badflag) {
|
||||
|
@ -742,27 +685,6 @@ struct hentry* SfxEntry::checkword(const char* word,
|
|||
return he;
|
||||
he = he->next_homonym; // check homonyms
|
||||
} while (he);
|
||||
|
||||
// obsolote stemming code (used only by the
|
||||
// experimental SuffixMgr:suggest_pos_stems)
|
||||
// store resulting root in wlst
|
||||
} else if (wlst && (*ns < maxSug)) {
|
||||
int cwrd = 1;
|
||||
for (int k = 0; k < *ns; k++)
|
||||
if (strcmp(tmpword, wlst[k]) == 0) {
|
||||
cwrd = 0;
|
||||
break;
|
||||
}
|
||||
if (cwrd) {
|
||||
wlst[*ns] = mystrdup(tmpword);
|
||||
if (wlst[*ns] == NULL) {
|
||||
for (int j = 0; j < *ns; j++)
|
||||
free(wlst[j]);
|
||||
*ns = -1;
|
||||
return NULL;
|
||||
}
|
||||
(*ns)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -775,7 +697,6 @@ struct hentry* SfxEntry::check_twosfx(const char* word,
|
|||
int optflags,
|
||||
PfxEntry* ppfx,
|
||||
const FLAG needflag) {
|
||||
struct hentry* he; // hash entry pointer
|
||||
PfxEntry* ep = ppfx;
|
||||
|
||||
// if this suffix is being cross checked with a prefix
|
||||
|
@ -813,17 +734,18 @@ struct hentry* SfxEntry::check_twosfx(const char* word,
|
|||
// if all conditions are met then recall suffix_check
|
||||
|
||||
if (test_condition(end, beg)) {
|
||||
struct hentry* he; // hash entry pointer
|
||||
if (ppfx) {
|
||||
// handle conditional suffix
|
||||
if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen))
|
||||
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL, NULL, 0, NULL,
|
||||
(FLAG)aflag, needflag);
|
||||
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL,
|
||||
(FLAG)aflag, needflag, IN_CPD_NOT);
|
||||
else
|
||||
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, optflags, ppfx, NULL, 0,
|
||||
NULL, (FLAG)aflag, needflag);
|
||||
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, optflags, ppfx,
|
||||
(FLAG)aflag, needflag, IN_CPD_NOT);
|
||||
} else {
|
||||
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL, NULL, 0, NULL,
|
||||
(FLAG)aflag, needflag);
|
||||
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL,
|
||||
(FLAG)aflag, needflag, IN_CPD_NOT);
|
||||
}
|
||||
if (he)
|
||||
return he;
|
||||
|
@ -833,23 +755,20 @@ struct hentry* SfxEntry::check_twosfx(const char* word,
|
|||
}
|
||||
|
||||
// see if two-level suffix is present in the word
|
||||
char* SfxEntry::check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
int optflags,
|
||||
PfxEntry* ppfx,
|
||||
const FLAG needflag) {
|
||||
std::string SfxEntry::check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
int optflags,
|
||||
PfxEntry* ppfx,
|
||||
const FLAG needflag) {
|
||||
PfxEntry* ep = ppfx;
|
||||
char* st;
|
||||
|
||||
char result[MAXLNLEN];
|
||||
|
||||
*result = '\0';
|
||||
std::string result;
|
||||
|
||||
// if this suffix is being cross checked with a prefix
|
||||
// but it does not support cross products skip it
|
||||
|
||||
if ((optflags & aeXPRODUCT) != 0 && (opts & aeXPRODUCT) == 0)
|
||||
return NULL;
|
||||
return result;
|
||||
|
||||
// upon entry suffix is 0 length or already matches the end of the word.
|
||||
// So if the remaining root word has positive length
|
||||
|
@ -883,40 +802,34 @@ char* SfxEntry::check_twosfx_morph(const char* word,
|
|||
if (ppfx) {
|
||||
// handle conditional suffix
|
||||
if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) {
|
||||
st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag,
|
||||
needflag);
|
||||
if (st) {
|
||||
std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag,
|
||||
needflag);
|
||||
if (!st.empty()) {
|
||||
if (ppfx->getMorph()) {
|
||||
mystrcat(result, ppfx->getMorph(), MAXLNLEN);
|
||||
mystrcat(result, " ", MAXLNLEN);
|
||||
result.append(ppfx->getMorph());
|
||||
result.append(" ");
|
||||
}
|
||||
mystrcat(result, st, MAXLNLEN);
|
||||
free(st);
|
||||
result.append(st);
|
||||
mychomp(result);
|
||||
}
|
||||
} else {
|
||||
st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, optflags, ppfx, aflag,
|
||||
needflag);
|
||||
if (st) {
|
||||
mystrcat(result, st, MAXLNLEN);
|
||||
free(st);
|
||||
std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, optflags, ppfx, aflag,
|
||||
needflag);
|
||||
if (!st.empty()) {
|
||||
result.append(st);
|
||||
mychomp(result);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
st =
|
||||
pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag, needflag);
|
||||
if (st) {
|
||||
mystrcat(result, st, MAXLNLEN);
|
||||
free(st);
|
||||
std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag, needflag);
|
||||
if (!st.empty()) {
|
||||
result.append(st);
|
||||
mychomp(result);
|
||||
}
|
||||
}
|
||||
if (*result)
|
||||
return mystrdup(result);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
// get next homonym with same affix
|
||||
|
@ -948,6 +861,11 @@ struct hentry* SfxEntry::get_next_homonym(struct hentry* he,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void SfxEntry::initReverseWord() {
|
||||
rappnd = appnd;
|
||||
reverseword(rappnd);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
Appendix: Understanding Affix Code
|
||||
|
|
|
@ -71,10 +71,8 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _AFFIX_HXX_
|
||||
#define _AFFIX_HXX_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
#ifndef AFFIX_HXX_
|
||||
#define AFFIX_HXX_
|
||||
|
||||
#include "atypes.hxx"
|
||||
#include "baseaffix.hxx"
|
||||
|
@ -82,7 +80,7 @@
|
|||
|
||||
/* A Prefix Entry */
|
||||
|
||||
class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry {
|
||||
class PfxEntry : public AffEntry {
|
||||
private:
|
||||
PfxEntry(const PfxEntry&);
|
||||
PfxEntry& operator=(const PfxEntry&);
|
||||
|
@ -96,10 +94,9 @@ class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry {
|
|||
PfxEntry* flgnxt;
|
||||
|
||||
public:
|
||||
PfxEntry(AffixMgr* pmgr, affentry* dp);
|
||||
~PfxEntry();
|
||||
explicit PfxEntry(AffixMgr* pmgr);
|
||||
|
||||
inline bool allowCross() { return ((opts & aeXPRODUCT) != 0); }
|
||||
bool allowCross() const { return ((opts & aeXPRODUCT) != 0); }
|
||||
struct hentry* checkword(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
|
@ -110,19 +107,19 @@ class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry {
|
|||
char in_compound,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
|
||||
char* check_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
std::string check_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
|
||||
char* check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
std::string check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
|
||||
inline FLAG getFlag() { return aflag; }
|
||||
inline const char* getKey() { return appnd.c_str(); }
|
||||
char* add(const char* word, size_t len);
|
||||
FLAG getFlag() { return aflag; }
|
||||
const char* getKey() { return appnd.c_str(); }
|
||||
std::string add(const char* word, size_t len);
|
||||
|
||||
inline short getKeyLen() { return appnd.size(); }
|
||||
|
||||
|
@ -147,7 +144,7 @@ class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry {
|
|||
|
||||
/* A Suffix Entry */
|
||||
|
||||
class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
|
||||
class SfxEntry : public AffEntry {
|
||||
private:
|
||||
SfxEntry(const SfxEntry&);
|
||||
SfxEntry& operator=(const SfxEntry&);
|
||||
|
@ -166,20 +163,16 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
|
|||
SfxEntry* eq_morph;
|
||||
|
||||
public:
|
||||
SfxEntry(AffixMgr* pmgr, affentry* dp);
|
||||
~SfxEntry();
|
||||
explicit SfxEntry(AffixMgr* pmgr);
|
||||
|
||||
inline bool allowCross() { return ((opts & aeXPRODUCT) != 0); }
|
||||
bool allowCross() const { return ((opts & aeXPRODUCT) != 0); }
|
||||
struct hentry* checkword(const char* word,
|
||||
int len,
|
||||
int optflags,
|
||||
PfxEntry* ppfx,
|
||||
char** wlst,
|
||||
int maxSug,
|
||||
int* ns,
|
||||
const FLAG cclass = FLAG_NULL,
|
||||
const FLAG needflag = FLAG_NULL,
|
||||
const FLAG badflag = FLAG_NULL);
|
||||
const FLAG cclass,
|
||||
const FLAG needflag,
|
||||
const FLAG badflag);
|
||||
|
||||
struct hentry* check_twosfx(const char* word,
|
||||
int len,
|
||||
|
@ -187,11 +180,11 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
|
|||
PfxEntry* ppfx,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
|
||||
char* check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
int optflags,
|
||||
PfxEntry* ppfx,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
std::string check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
int optflags,
|
||||
PfxEntry* ppfx,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
struct hentry* get_next_homonym(struct hentry* he);
|
||||
struct hentry* get_next_homonym(struct hentry* word,
|
||||
int optflags,
|
||||
|
@ -199,9 +192,9 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
|
|||
const FLAG cclass,
|
||||
const FLAG needflag);
|
||||
|
||||
inline FLAG getFlag() { return aflag; }
|
||||
inline const char* getKey() { return rappnd.c_str(); }
|
||||
char* add(const char* word, size_t len);
|
||||
FLAG getFlag() { return aflag; }
|
||||
const char* getKey() { return rappnd.c_str(); }
|
||||
std::string add(const char* word, size_t len);
|
||||
|
||||
inline const char* getMorph() { return morphcode; }
|
||||
|
||||
|
@ -224,6 +217,7 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
|
|||
inline void setNextNE(SfxEntry* ptr) { nextne = ptr; }
|
||||
inline void setNextEQ(SfxEntry* ptr) { nexteq = ptr; }
|
||||
inline void setFlgNxt(SfxEntry* ptr) { flgnxt = ptr; }
|
||||
void initReverseWord();
|
||||
|
||||
inline char* nextchar(char* p);
|
||||
inline int test_condition(const char* st, const char* begin);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -71,14 +71,13 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _AFFIXMGR_HXX_
|
||||
#define _AFFIXMGR_HXX_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
#ifndef AFFIXMGR_HXX_
|
||||
#define AFFIXMGR_HXX_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atypes.hxx"
|
||||
#include "baseaffix.hxx"
|
||||
|
@ -93,17 +92,16 @@
|
|||
class PfxEntry;
|
||||
class SfxEntry;
|
||||
|
||||
class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
||||
class AffixMgr {
|
||||
PfxEntry* pStart[SETSIZE];
|
||||
SfxEntry* sStart[SETSIZE];
|
||||
PfxEntry* pFlag[SETSIZE];
|
||||
SfxEntry* sFlag[SETSIZE];
|
||||
HashMgr* pHMgr;
|
||||
HashMgr** alldic;
|
||||
int* maxdic;
|
||||
char* keystring;
|
||||
char* trystring;
|
||||
char* encoding;
|
||||
const std::vector<HashMgr*>& alldic;
|
||||
const HashMgr* pHMgr;
|
||||
std::string keystring;
|
||||
std::string trystring;
|
||||
std::string encoding;
|
||||
struct cs_info* csconv;
|
||||
int utf8;
|
||||
int complexprefixes;
|
||||
|
@ -125,19 +123,19 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
|||
FLAG nongramsuggest;
|
||||
FLAG needaffix;
|
||||
int cpdmin;
|
||||
int numrep;
|
||||
replentry* reptable;
|
||||
bool parsedrep;
|
||||
std::vector<replentry> reptable;
|
||||
RepList* iconvtable;
|
||||
RepList* oconvtable;
|
||||
int nummap;
|
||||
mapentry* maptable;
|
||||
int numbreak;
|
||||
char** breaktable;
|
||||
int numcheckcpd;
|
||||
patentry* checkcpdtable;
|
||||
bool parsedmaptable;
|
||||
std::vector<mapentry> maptable;
|
||||
bool parsedbreaktable;
|
||||
std::vector<std::string> breaktable;
|
||||
bool parsedcheckcpd;
|
||||
std::vector<patentry> checkcpdtable;
|
||||
int simplifiedcpd;
|
||||
int numdefcpd;
|
||||
flagentry* defcpdtable;
|
||||
bool parseddefcpd;
|
||||
std::vector<flagentry> defcpdtable;
|
||||
phonetable* phone;
|
||||
int maxngramsugs;
|
||||
int maxcpdsugs;
|
||||
|
@ -147,10 +145,9 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
|||
int sugswithdots;
|
||||
int cpdwordmax;
|
||||
int cpdmaxsyllable;
|
||||
char* cpdvowels;
|
||||
w_char* cpdvowels_utf16;
|
||||
int cpdvowels_utf16_len;
|
||||
char* cpdsyllablenum;
|
||||
std::string cpdvowels; // vowels (for calculating of Hungarian compounding limit,
|
||||
std::vector<w_char> cpdvowels_utf16; //vowels for UTF-8 encoding
|
||||
std::string cpdsyllablenum; // syllable count incrementing flag
|
||||
const char* pfxappnd; // BUG: not stateless
|
||||
const char* sfxappnd; // BUG: not stateless
|
||||
int sfxextra; // BUG: not stateless
|
||||
|
@ -159,12 +156,12 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
|||
SfxEntry* sfx; // BUG: not stateless
|
||||
PfxEntry* pfx; // BUG: not stateless
|
||||
int checknum;
|
||||
char* wordchars;
|
||||
std::string wordchars; // letters + spec. word characters
|
||||
std::vector<w_char> wordchars_utf16;
|
||||
char* ignorechars;
|
||||
std::string ignorechars; // letters + spec. word characters
|
||||
std::vector<w_char> ignorechars_utf16;
|
||||
char* version;
|
||||
char* lang;
|
||||
std::string version; // affix and dictionary file version string
|
||||
std::string lang; // language
|
||||
int langnum;
|
||||
FLAG lemma_present;
|
||||
FLAG circumfix;
|
||||
|
@ -182,7 +179,7 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
|||
// affix)
|
||||
|
||||
public:
|
||||
AffixMgr(const char* affpath, HashMgr** ptr, int* md, const char* key = NULL);
|
||||
AffixMgr(const char* affpath, const std::vector<HashMgr*>& ptr, const char* key = NULL);
|
||||
~AffixMgr();
|
||||
struct hentry* affix_check(const char* word,
|
||||
int len,
|
||||
|
@ -202,9 +199,6 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
|||
int len,
|
||||
int sfxopts,
|
||||
PfxEntry* ppfx,
|
||||
char** wlst,
|
||||
int maxSug,
|
||||
int* ns,
|
||||
const FLAG cclass = FLAG_NULL,
|
||||
const FLAG needflag = FLAG_NULL,
|
||||
char in_compound = IN_CPD_NOT);
|
||||
|
@ -214,39 +208,39 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
|||
PfxEntry* ppfx,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
|
||||
char* affix_check_morph(const char* word,
|
||||
int len,
|
||||
const FLAG needflag = FLAG_NULL,
|
||||
char in_compound = IN_CPD_NOT);
|
||||
char* prefix_check_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
char* suffix_check_morph(const char* word,
|
||||
int len,
|
||||
int sfxopts,
|
||||
PfxEntry* ppfx,
|
||||
const FLAG cclass = FLAG_NULL,
|
||||
const FLAG needflag = FLAG_NULL,
|
||||
char in_compound = IN_CPD_NOT);
|
||||
std::string affix_check_morph(const char* word,
|
||||
int len,
|
||||
const FLAG needflag = FLAG_NULL,
|
||||
char in_compound = IN_CPD_NOT);
|
||||
std::string prefix_check_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
std::string suffix_check_morph(const char* word,
|
||||
int len,
|
||||
int sfxopts,
|
||||
PfxEntry* ppfx,
|
||||
const FLAG cclass = FLAG_NULL,
|
||||
const FLAG needflag = FLAG_NULL,
|
||||
char in_compound = IN_CPD_NOT);
|
||||
|
||||
char* prefix_check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
char* suffix_check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
int sfxopts,
|
||||
PfxEntry* ppfx,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
std::string prefix_check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
char in_compound,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
std::string suffix_check_twosfx_morph(const char* word,
|
||||
int len,
|
||||
int sfxopts,
|
||||
PfxEntry* ppfx,
|
||||
const FLAG needflag = FLAG_NULL);
|
||||
|
||||
char* morphgen(const char* ts,
|
||||
int wl,
|
||||
const unsigned short* ap,
|
||||
unsigned short al,
|
||||
const char* morph,
|
||||
const char* targetmorph,
|
||||
int level);
|
||||
std::string morphgen(const char* ts,
|
||||
int wl,
|
||||
const unsigned short* ap,
|
||||
unsigned short al,
|
||||
const char* morph,
|
||||
const char* targetmorph,
|
||||
int level);
|
||||
|
||||
int expand_rootword(struct guessword* wlst,
|
||||
int maxn,
|
||||
|
@ -273,8 +267,7 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
|||
int cpdcase_check(const char* word, int len);
|
||||
inline int candidate_check(const char* word, int len);
|
||||
void setcminmax(int* cmin, int* cmax, const char* word, int len);
|
||||
struct hentry* compound_check(const char* word,
|
||||
int len,
|
||||
struct hentry* compound_check(const std::string& word,
|
||||
short wordnum,
|
||||
short numsyllable,
|
||||
short maxwordnum,
|
||||
|
@ -294,47 +287,37 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
|||
hentry** words,
|
||||
hentry** rwords,
|
||||
char hu_mov_rule,
|
||||
char** result,
|
||||
char* partresult);
|
||||
std::string& result,
|
||||
const std::string* partresult);
|
||||
|
||||
int get_suffix_words(short unsigned* suff,
|
||||
std::vector<std::string> get_suffix_words(short unsigned* suff,
|
||||
int len,
|
||||
const char* root_word,
|
||||
char** slst);
|
||||
const char* root_word);
|
||||
|
||||
struct hentry* lookup(const char* word);
|
||||
int get_numrep() const;
|
||||
struct replentry* get_reptable() const;
|
||||
const std::vector<replentry>& get_reptable() const;
|
||||
RepList* get_iconvtable() const;
|
||||
RepList* get_oconvtable() const;
|
||||
struct phonetable* get_phonetable() const;
|
||||
int get_nummap() const;
|
||||
struct mapentry* get_maptable() const;
|
||||
int get_numbreak() const;
|
||||
char** get_breaktable() const;
|
||||
char* get_encoding();
|
||||
const std::vector<mapentry>& get_maptable() const;
|
||||
const std::vector<std::string>& get_breaktable() const;
|
||||
const std::string& get_encoding();
|
||||
int get_langnum() const;
|
||||
char* get_key_string();
|
||||
char* get_try_string() const;
|
||||
const char* get_wordchars() const;
|
||||
const std::string& get_wordchars() const;
|
||||
const std::vector<w_char>& get_wordchars_utf16() const;
|
||||
char* get_ignore() const;
|
||||
const char* get_ignore() const;
|
||||
const std::vector<w_char>& get_ignore_utf16() const;
|
||||
int get_compound() const;
|
||||
FLAG get_compoundflag() const;
|
||||
FLAG get_compoundbegin() const;
|
||||
FLAG get_forbiddenword() const;
|
||||
FLAG get_nosuggest() const;
|
||||
FLAG get_nongramsuggest() const;
|
||||
FLAG get_needaffix() const;
|
||||
FLAG get_onlyincompound() const;
|
||||
FLAG get_compoundroot() const;
|
||||
FLAG get_lemma_present() const;
|
||||
int get_checknum() const;
|
||||
const char* get_prefix() const;
|
||||
const char* get_suffix() const;
|
||||
const char* get_derived() const;
|
||||
const char* get_version() const;
|
||||
const std::string& get_version() const;
|
||||
int have_contclass() const;
|
||||
int get_utf8() const;
|
||||
int get_complexprefixes() const;
|
||||
|
@ -355,26 +338,25 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
|
|||
|
||||
private:
|
||||
int parse_file(const char* affpath, const char* key);
|
||||
int parse_flag(char* line, unsigned short* out, FileMgr* af);
|
||||
int parse_num(char* line, int* out, FileMgr* af);
|
||||
int parse_cpdsyllable(char* line, FileMgr* af);
|
||||
int parse_reptable(char* line, FileMgr* af);
|
||||
int parse_convtable(char* line,
|
||||
bool parse_flag(const std::string& line, unsigned short* out, FileMgr* af);
|
||||
bool parse_num(const std::string& line, int* out, FileMgr* af);
|
||||
bool parse_cpdsyllable(const std::string& line, FileMgr* af);
|
||||
bool parse_reptable(const std::string& line, FileMgr* af);
|
||||
bool parse_convtable(const std::string& line,
|
||||
FileMgr* af,
|
||||
RepList** rl,
|
||||
const char* keyword);
|
||||
int parse_phonetable(char* line, FileMgr* af);
|
||||
int parse_maptable(char* line, FileMgr* af);
|
||||
int parse_breaktable(char* line, FileMgr* af);
|
||||
int parse_checkcpdtable(char* line, FileMgr* af);
|
||||
int parse_defcpdtable(char* line, FileMgr* af);
|
||||
int parse_affix(char* line, const char at, FileMgr* af, char* dupflags);
|
||||
const std::string& keyword);
|
||||
bool parse_phonetable(const std::string& line, FileMgr* af);
|
||||
bool parse_maptable(const std::string& line, FileMgr* af);
|
||||
bool parse_breaktable(const std::string& line, FileMgr* af);
|
||||
bool parse_checkcpdtable(const std::string& line, FileMgr* af);
|
||||
bool parse_defcpdtable(const std::string& line, FileMgr* af);
|
||||
bool parse_affix(const std::string& line, const char at, FileMgr* af, char* dupflags);
|
||||
|
||||
void reverse_condition(std::string&);
|
||||
void debugflag(char* result, unsigned short flag);
|
||||
std::string& debugflag(std::string& result, unsigned short flag);
|
||||
int condlen(const char*);
|
||||
int encodeit(affentry& entry, const char* cs);
|
||||
int encodeit(AffEntry& entry, const char* cs);
|
||||
int build_pfxtree(PfxEntry* pfxptr);
|
||||
int build_sfxtree(SfxEntry* sfxptr);
|
||||
int process_pfx_order();
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _ATYPES_HXX_
|
||||
#define _ATYPES_HXX_
|
||||
#ifndef ATYPES_HXX_
|
||||
#define ATYPES_HXX_
|
||||
|
||||
#ifndef HUNSPELL_WARNING
|
||||
#include <stdio.h>
|
||||
|
@ -55,15 +55,15 @@ static inline void HUNSPELL_WARNING(FILE*, const char*, ...) {}
|
|||
// HUNSTEM def.
|
||||
#define HUNSTEM
|
||||
|
||||
#include "hashmgr.hxx"
|
||||
#include "w_char.hxx"
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define SETSIZE 256
|
||||
#define CONTSIZE 65536
|
||||
|
||||
// affentry options
|
||||
// AffEntry options
|
||||
#define aeXPRODUCT (1 << 0)
|
||||
#define aeUTF8 (1 << 1)
|
||||
#define aeALIASF (1 << 2)
|
||||
|
@ -85,8 +85,6 @@ static inline void HUNSPELL_WARNING(FILE*, const char*, ...) {}
|
|||
#define SPELL_ORIGCAP (1 << 5)
|
||||
#define SPELL_WARN (1 << 6)
|
||||
|
||||
#define MAXLNLEN 8192
|
||||
|
||||
#define MINCPDLEN 3
|
||||
#define MAXCOMPOUND 10
|
||||
#define MAXCONDLEN 20
|
||||
|
@ -100,46 +98,25 @@ static inline void HUNSPELL_WARNING(FILE*, const char*, ...) {}
|
|||
|
||||
#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
|
||||
|
||||
struct affentry {
|
||||
std::string strip;
|
||||
std::string appnd;
|
||||
char numconds;
|
||||
char opts;
|
||||
unsigned short aflag;
|
||||
unsigned short* contclass;
|
||||
short contclasslen;
|
||||
union {
|
||||
char conds[MAXCONDLEN];
|
||||
struct {
|
||||
char conds1[MAXCONDLEN_1];
|
||||
char* conds2;
|
||||
} l;
|
||||
} c;
|
||||
char* morphcode;
|
||||
};
|
||||
|
||||
struct guessword {
|
||||
char* word;
|
||||
bool allow;
|
||||
char* orig;
|
||||
};
|
||||
|
||||
struct mapentry {
|
||||
char** set;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct flagentry {
|
||||
FLAG* def;
|
||||
int len;
|
||||
};
|
||||
typedef std::vector<std::string> mapentry;
|
||||
typedef std::vector<FLAG> flagentry;
|
||||
|
||||
struct patentry {
|
||||
char* pattern;
|
||||
char* pattern2;
|
||||
char* pattern3;
|
||||
std::string pattern;
|
||||
std::string pattern2;
|
||||
std::string pattern3;
|
||||
FLAG cond;
|
||||
FLAG cond2;
|
||||
patentry()
|
||||
: cond(FLAG_NULL)
|
||||
, cond2(FLAG_NULL) {
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,18 +38,17 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _BASEAFF_HXX_
|
||||
#define _BASEAFF_HXX_
|
||||
#ifndef BASEAFF_HXX_
|
||||
#define BASEAFF_HXX_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
#include <string>
|
||||
|
||||
class LIBHUNSPELL_DLL_EXPORTED AffEntry {
|
||||
class AffEntry {
|
||||
private:
|
||||
AffEntry(const AffEntry&);
|
||||
AffEntry& operator=(const AffEntry&);
|
||||
|
||||
protected:
|
||||
public:
|
||||
AffEntry()
|
||||
: numconds(0),
|
||||
opts(0),
|
||||
|
@ -57,6 +56,7 @@ class LIBHUNSPELL_DLL_EXPORTED AffEntry {
|
|||
morphcode(0),
|
||||
contclass(NULL),
|
||||
contclasslen(0) {}
|
||||
virtual ~AffEntry();
|
||||
std::string appnd;
|
||||
std::string strip;
|
||||
unsigned char numconds;
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "csutil.hxx"
|
||||
#include "atypes.hxx"
|
||||
|
@ -122,26 +123,24 @@ static struct unicode_info2* utf_tbl = NULL;
|
|||
static int utf_tbl_count =
|
||||
0; // utf_tbl can be used by multiple Hunspell instances
|
||||
|
||||
FILE* myfopen(const char* path, const char* mode) {
|
||||
#ifdef _WIN32
|
||||
void myopen(std::ifstream& stream, const char* path, std::ios_base::openmode mode)
|
||||
{
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
#define WIN32_LONG_PATH_PREFIX "\\\\?\\"
|
||||
if (strncmp(path, WIN32_LONG_PATH_PREFIX, 4) == 0) {
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
|
||||
wchar_t* buff = (wchar_t*)malloc(len * sizeof(wchar_t));
|
||||
wchar_t* buff2 = (wchar_t*)malloc(len * sizeof(wchar_t));
|
||||
FILE* f = NULL;
|
||||
if (buff && buff2) {
|
||||
MultiByteToWideChar(CP_UTF8, 0, path, -1, buff, len);
|
||||
if (_wfullpath(buff2, buff, len) != NULL) {
|
||||
f = _wfopen(buff2, (strcmp(mode, "r") == 0) ? L"r" : L"rb");
|
||||
}
|
||||
free(buff);
|
||||
free(buff2);
|
||||
wchar_t* buff = new wchar_t[len];
|
||||
wchar_t* buff2 = new wchar_t[len];
|
||||
MultiByteToWideChar(CP_UTF8, 0, path, -1, buff, len);
|
||||
if (_wfullpath(buff2, buff, len) != NULL) {
|
||||
stream.open(buff2, mode);
|
||||
}
|
||||
return f;
|
||||
delete [] buff;
|
||||
delete [] buff2;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return fopen(path, mode);
|
||||
stream.open(path, mode);
|
||||
}
|
||||
|
||||
std::string& u16_u8(std::string& dest, const std::vector<w_char>& src) {
|
||||
|
@ -218,7 +217,7 @@ int u8_u16(std::vector<w_char>& dest, const std::string& src) {
|
|||
case 0xd0: { // 2-byte UTF-8 codes
|
||||
if ((*(u8 + 1) & 0xc0) == 0x80) {
|
||||
u2.h = (*u8 & 0x1f) >> 2;
|
||||
u2.l = (*u8 << 6) + (*(u8 + 1) & 0x3f);
|
||||
u2.l = (static_cast<unsigned char>(*u8) << 6) + (*(u8 + 1) & 0x3f);
|
||||
++u8;
|
||||
} else {
|
||||
HUNSPELL_WARNING(stderr,
|
||||
|
@ -275,34 +274,35 @@ int u8_u16(std::vector<w_char>& dest, const std::string& src) {
|
|||
return dest.size();
|
||||
}
|
||||
|
||||
// strip strings into token based on single char delimiter
|
||||
// acts like strsep() but only uses a delim char and not
|
||||
// a delim string
|
||||
// default delimiter: white space characters
|
||||
namespace {
|
||||
class is_any_of {
|
||||
public:
|
||||
explicit is_any_of(const std::string& in) : chars(in) {}
|
||||
|
||||
char* mystrsep(char** stringp, const char delim) {
|
||||
char* mp = *stringp;
|
||||
if (*mp != '\0') {
|
||||
char* dp;
|
||||
if (delim) {
|
||||
dp = strchr(mp, delim);
|
||||
} else {
|
||||
// don't use isspace() here, the string can be in some random charset
|
||||
// that's way different than the locale's
|
||||
for (dp = mp; (*dp && *dp != ' ' && *dp != '\t'); dp++)
|
||||
;
|
||||
if (!*dp)
|
||||
dp = NULL;
|
||||
}
|
||||
if (dp) {
|
||||
*stringp = dp + 1;
|
||||
*dp = '\0';
|
||||
} else {
|
||||
*stringp = mp + strlen(mp);
|
||||
}
|
||||
return mp;
|
||||
}
|
||||
return NULL;
|
||||
bool operator()(char c) { return chars.find(c) != std::string::npos; }
|
||||
|
||||
private:
|
||||
std::string chars;
|
||||
};
|
||||
}
|
||||
|
||||
std::string::const_iterator mystrsep(const std::string &str,
|
||||
std::string::const_iterator& start) {
|
||||
std::string::const_iterator end = str.end();
|
||||
|
||||
is_any_of op(" \t");
|
||||
// don't use isspace() here, the string can be in some random charset
|
||||
// that's way different than the locale's
|
||||
std::string::const_iterator sp = start;
|
||||
while (sp != end && op(*sp))
|
||||
++sp;
|
||||
|
||||
std::string::const_iterator dp = sp;
|
||||
while (dp != end && !op(*dp))
|
||||
++dp;
|
||||
|
||||
start = dp;
|
||||
return sp;
|
||||
}
|
||||
|
||||
// replaces strdup with ansi version
|
||||
|
@ -320,142 +320,98 @@ char* mystrdup(const char* s) {
|
|||
return d;
|
||||
}
|
||||
|
||||
// strcat for limited length destination string
|
||||
char* mystrcat(char* dest, const char* st, int max) {
|
||||
int len;
|
||||
int len2;
|
||||
if (dest == NULL || st == NULL)
|
||||
return dest;
|
||||
len = strlen(dest);
|
||||
len2 = strlen(st);
|
||||
if (len + len2 + 1 > max)
|
||||
return dest;
|
||||
strcpy(dest + len, st);
|
||||
return dest;
|
||||
}
|
||||
|
||||
// remove cross-platform text line end characters
|
||||
void mychomp(char* s) {
|
||||
size_t k = strlen(s);
|
||||
if ((k > 0) && ((*(s + k - 1) == '\r') || (*(s + k - 1) == '\n')))
|
||||
*(s + k - 1) = '\0';
|
||||
if ((k > 1) && (*(s + k - 2) == '\r'))
|
||||
*(s + k - 2) = '\0';
|
||||
void mychomp(std::string& s) {
|
||||
size_t k = s.size();
|
||||
size_t newsize = k;
|
||||
if ((k > 0) && ((s[k - 1] == '\r') || (s[k - 1] == '\n')))
|
||||
--newsize;
|
||||
if ((k > 1) && (s[k - 2] == '\r'))
|
||||
--newsize;
|
||||
s.resize(newsize);
|
||||
}
|
||||
|
||||
// break text to lines
|
||||
// return number of lines
|
||||
int line_tok(const char* text, char*** lines, char breakchar) {
|
||||
int linenum = 0;
|
||||
if (!text) {
|
||||
return linenum;
|
||||
}
|
||||
char* dup = mystrdup(text);
|
||||
char* p = strchr(dup, breakchar);
|
||||
while (p) {
|
||||
linenum++;
|
||||
*p = '\0';
|
||||
p++;
|
||||
p = strchr(p, breakchar);
|
||||
}
|
||||
linenum++;
|
||||
*lines = (char**)malloc(linenum * sizeof(char*));
|
||||
if (!(*lines)) {
|
||||
free(dup);
|
||||
return 0;
|
||||
std::vector<std::string> line_tok(const std::string& text, char breakchar) {
|
||||
std::vector<std::string> ret;
|
||||
if (text.empty()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
p = dup;
|
||||
int l = 0;
|
||||
for (int i = 0; i < linenum; i++) {
|
||||
if (*p != '\0') {
|
||||
(*lines)[l] = mystrdup(p);
|
||||
if (!(*lines)[l]) {
|
||||
for (i = 0; i < l; i++)
|
||||
free((*lines)[i]);
|
||||
free(dup);
|
||||
return 0;
|
||||
}
|
||||
l++;
|
||||
std::stringstream ss(text);
|
||||
std::string tok;
|
||||
while(std::getline(ss, tok, breakchar)) {
|
||||
if (!tok.empty()) {
|
||||
ret.push_back(tok);
|
||||
}
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
free(dup);
|
||||
if (!l) {
|
||||
free(*lines);
|
||||
*lines = NULL;
|
||||
}
|
||||
return l;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// uniq line in place
|
||||
char* line_uniq(char* text, char breakchar) {
|
||||
char** lines;
|
||||
int linenum = line_tok(text, &lines, breakchar);
|
||||
int i;
|
||||
strcpy(text, lines[0]);
|
||||
for (i = 1; i < linenum; i++) {
|
||||
int dup = 0;
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (strcmp(lines[i], lines[j]) == 0) {
|
||||
dup = 1;
|
||||
void line_uniq(std::string& text, char breakchar)
|
||||
{
|
||||
std::vector<std::string> lines = line_tok(text, breakchar);
|
||||
text.clear();
|
||||
if (lines.empty()) {
|
||||
return;
|
||||
}
|
||||
text = lines[0];
|
||||
for (size_t i = 1; i < lines.size(); ++i) {
|
||||
bool dup = false;
|
||||
for (size_t j = 0; j < i; ++j) {
|
||||
if (lines[i] == lines[j]) {
|
||||
dup = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dup) {
|
||||
if ((i > 1) || (*(lines[0]) != '\0')) {
|
||||
sprintf(text + strlen(text), "%c", breakchar);
|
||||
}
|
||||
strcat(text, lines[i]);
|
||||
if (!text.empty())
|
||||
text.push_back(breakchar);
|
||||
text.append(lines[i]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < linenum; i++) {
|
||||
free(lines[i]);
|
||||
}
|
||||
free(lines);
|
||||
return text;
|
||||
}
|
||||
|
||||
// uniq and boundary for compound analysis: "1\n\2\n\1" -> " ( \1 | \2 ) "
|
||||
char* line_uniq_app(char** text, char breakchar) {
|
||||
if (!strchr(*text, breakchar)) {
|
||||
return *text;
|
||||
void line_uniq_app(std::string& text, char breakchar) {
|
||||
if (text.find(breakchar) == std::string::npos) {
|
||||
return;
|
||||
}
|
||||
|
||||
char** lines;
|
||||
int i;
|
||||
int linenum = line_tok(*text, &lines, breakchar);
|
||||
int dup = 0;
|
||||
for (i = 0; i < linenum; i++) {
|
||||
for (int j = 0; j < (i - 1); j++) {
|
||||
if (strcmp(lines[i], lines[j]) == 0) {
|
||||
*(lines[i]) = '\0';
|
||||
dup++;
|
||||
std::vector<std::string> lines = line_tok(text, breakchar);
|
||||
text.clear();
|
||||
if (lines.empty()) {
|
||||
return;
|
||||
}
|
||||
text = lines[0];
|
||||
for (size_t i = 1; i < lines.size(); ++i) {
|
||||
bool dup = false;
|
||||
for (size_t j = 0; j < i; ++j) {
|
||||
if (lines[i] == lines[j]) {
|
||||
dup = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((linenum - dup) == 1) {
|
||||
strcpy(*text, lines[0]);
|
||||
freelist(&lines, linenum);
|
||||
return *text;
|
||||
}
|
||||
char* newtext = (char*)malloc(strlen(*text) + 2 * linenum + 3 + 1);
|
||||
if (newtext) {
|
||||
free(*text);
|
||||
*text = newtext;
|
||||
} else {
|
||||
freelist(&lines, linenum);
|
||||
return *text;
|
||||
}
|
||||
strcpy(*text, " ( ");
|
||||
for (i = 0; i < linenum; i++)
|
||||
if (*(lines[i])) {
|
||||
sprintf(*text + strlen(*text), "%s%s", lines[i], " | ");
|
||||
if (!dup) {
|
||||
if (!text.empty())
|
||||
text.push_back(breakchar);
|
||||
text.append(lines[i]);
|
||||
}
|
||||
(*text)[strlen(*text) - 2] = ')'; // " ) "
|
||||
freelist(&lines, linenum);
|
||||
return *text;
|
||||
}
|
||||
|
||||
if (lines.size() == 1) {
|
||||
text = lines[0];
|
||||
return;
|
||||
}
|
||||
|
||||
text.assign(" ( ");
|
||||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
text.append(lines[i]);
|
||||
text.append(" | ");
|
||||
}
|
||||
text[text.size() - 2] = ')'; // " ) "
|
||||
}
|
||||
|
||||
// append s to ends of every lines in text
|
||||
|
@ -469,111 +425,6 @@ std::string& strlinecat(std::string& str, const std::string& apd) {
|
|||
return str;
|
||||
}
|
||||
|
||||
// morphcmp(): compare MORPH_DERI_SFX, MORPH_INFL_SFX and MORPH_TERM_SFX fields
|
||||
// in the first line of the inputs
|
||||
// return 0, if inputs equal
|
||||
// return 1, if inputs may equal with a secondary suffix
|
||||
// otherwise return -1
|
||||
int morphcmp(const char* s, const char* t) {
|
||||
int se = 0;
|
||||
int te = 0;
|
||||
const char* sl;
|
||||
const char* tl;
|
||||
const char* olds;
|
||||
const char* oldt;
|
||||
if (!s || !t)
|
||||
return 1;
|
||||
olds = s;
|
||||
sl = strchr(s, '\n');
|
||||
s = strstr(s, MORPH_DERI_SFX);
|
||||
if (!s || (sl && sl < s))
|
||||
s = strstr(olds, MORPH_INFL_SFX);
|
||||
if (!s || (sl && sl < s)) {
|
||||
s = strstr(olds, MORPH_TERM_SFX);
|
||||
olds = NULL;
|
||||
}
|
||||
oldt = t;
|
||||
tl = strchr(t, '\n');
|
||||
t = strstr(t, MORPH_DERI_SFX);
|
||||
if (!t || (tl && tl < t))
|
||||
t = strstr(oldt, MORPH_INFL_SFX);
|
||||
if (!t || (tl && tl < t)) {
|
||||
t = strstr(oldt, MORPH_TERM_SFX);
|
||||
oldt = NULL;
|
||||
}
|
||||
while (s && t && (!sl || sl > s) && (!tl || tl > t)) {
|
||||
s += MORPH_TAG_LEN;
|
||||
t += MORPH_TAG_LEN;
|
||||
se = 0;
|
||||
te = 0;
|
||||
while ((*s == *t) && !se && !te) {
|
||||
s++;
|
||||
t++;
|
||||
switch (*s) {
|
||||
case ' ':
|
||||
case '\n':
|
||||
case '\t':
|
||||
case '\0':
|
||||
se = 1;
|
||||
}
|
||||
switch (*t) {
|
||||
case ' ':
|
||||
case '\n':
|
||||
case '\t':
|
||||
case '\0':
|
||||
te = 1;
|
||||
}
|
||||
}
|
||||
if (!se || !te) {
|
||||
// not terminal suffix difference
|
||||
if (olds)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
olds = s;
|
||||
s = strstr(s, MORPH_DERI_SFX);
|
||||
if (!s || (sl && sl < s))
|
||||
s = strstr(olds, MORPH_INFL_SFX);
|
||||
if (!s || (sl && sl < s)) {
|
||||
s = strstr(olds, MORPH_TERM_SFX);
|
||||
olds = NULL;
|
||||
}
|
||||
oldt = t;
|
||||
t = strstr(t, MORPH_DERI_SFX);
|
||||
if (!t || (tl && tl < t))
|
||||
t = strstr(oldt, MORPH_INFL_SFX);
|
||||
if (!t || (tl && tl < t)) {
|
||||
t = strstr(oldt, MORPH_TERM_SFX);
|
||||
oldt = NULL;
|
||||
}
|
||||
}
|
||||
if (!s && !t && se && te)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_sfxcount(const char* morph) {
|
||||
if (!morph || !*morph)
|
||||
return 0;
|
||||
int n = 0;
|
||||
const char* old = morph;
|
||||
morph = strstr(morph, MORPH_DERI_SFX);
|
||||
if (!morph)
|
||||
morph = strstr(old, MORPH_INFL_SFX);
|
||||
if (!morph)
|
||||
morph = strstr(old, MORPH_TERM_SFX);
|
||||
while (morph) {
|
||||
n++;
|
||||
old = morph;
|
||||
morph = strstr(morph + 1, MORPH_DERI_SFX);
|
||||
if (!morph)
|
||||
morph = strstr(old + 1, MORPH_INFL_SFX);
|
||||
if (!morph)
|
||||
morph = strstr(old + 1, MORPH_TERM_SFX);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int fieldlen(const char* r) {
|
||||
int n = 0;
|
||||
while (r && *r != ' ' && *r != '\t' && *r != '\0' && *r != '\n') {
|
||||
|
@ -615,33 +466,6 @@ std::string& mystrrep(std::string& str,
|
|||
return str;
|
||||
}
|
||||
|
||||
char* mystrrep(char* word, const char* pat, const char* rep) {
|
||||
char* pos = strstr(word, pat);
|
||||
if (pos) {
|
||||
int replen = strlen(rep);
|
||||
int patlen = strlen(pat);
|
||||
while (pos) {
|
||||
if (replen < patlen) {
|
||||
char* end = word + strlen(word);
|
||||
char* next = pos + replen;
|
||||
char* prev = pos + strlen(pat);
|
||||
for (; prev < end;* next = *prev, prev++, next++)
|
||||
;
|
||||
*next = '\0';
|
||||
} else if (replen > patlen) {
|
||||
char* end = pos + patlen;
|
||||
char* next = word + strlen(word) + replen - patlen;
|
||||
char* prev = next - replen + patlen;
|
||||
for (; prev >= end;* next = *prev, prev--, next--)
|
||||
;
|
||||
}
|
||||
strncpy(pos, rep, replen);
|
||||
pos = strstr(word, pat);
|
||||
}
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
// reverse word
|
||||
size_t reverseword(std::string& word) {
|
||||
std::reverse(word.begin(), word.end());
|
||||
|
@ -657,35 +481,19 @@ size_t reverseword_utf(std::string& word) {
|
|||
return w.size();
|
||||
}
|
||||
|
||||
int uniqlist(char** list, int n) {
|
||||
int i;
|
||||
if (n < 2)
|
||||
return n;
|
||||
for (i = 0; i < n; i++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (list[j] && list[i] && (strcmp(list[j], list[i]) == 0)) {
|
||||
free(list[i]);
|
||||
list[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int m = 1;
|
||||
for (i = 1; i < n; i++)
|
||||
if (list[i]) {
|
||||
list[m] = list[i];
|
||||
m++;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
void uniqlist(std::vector<std::string>& list) {
|
||||
if (list.size() < 2)
|
||||
return;
|
||||
|
||||
void freelist(char*** list, int n) {
|
||||
if (list && *list) {
|
||||
for (int i = 0; i < n; i++)
|
||||
free((*list)[i]);
|
||||
free(*list);
|
||||
*list = NULL;
|
||||
std::vector<std::string> ret;
|
||||
ret.push_back(list[0]);
|
||||
|
||||
for (size_t i = 1; i < list.size(); ++i) {
|
||||
if (std::find(ret.begin(), ret.end(), list[i]) == ret.end())
|
||||
ret.push_back(list[i]);
|
||||
}
|
||||
|
||||
list.swap(ret);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -2457,9 +2265,9 @@ static void toAsciiLowerAndRemoveNonAlphanumeric(const char* pName,
|
|||
*pBuf = '\0';
|
||||
}
|
||||
|
||||
struct cs_info* get_current_cs(const char* es) {
|
||||
char* normalized_encoding = new char[strlen(es) + 1];
|
||||
toAsciiLowerAndRemoveNonAlphanumeric(es, normalized_encoding);
|
||||
struct cs_info* get_current_cs(const std::string& es) {
|
||||
char* normalized_encoding = new char[es.size() + 1];
|
||||
toAsciiLowerAndRemoveNonAlphanumeric(es.c_str(), normalized_encoding);
|
||||
|
||||
struct cs_info* ccs = NULL;
|
||||
int n = sizeof(encds) / sizeof(encds[0]);
|
||||
|
@ -2474,7 +2282,7 @@ struct cs_info* get_current_cs(const char* es) {
|
|||
|
||||
if (!ccs) {
|
||||
HUNSPELL_WARNING(stderr,
|
||||
"error: unknown encoding %s: using %s as fallback\n", es,
|
||||
"error: unknown encoding %s: using %s as fallback\n", es.c_str(),
|
||||
encds[0].enc_name);
|
||||
ccs = encds[0].cs_table;
|
||||
}
|
||||
|
@ -2485,7 +2293,7 @@ struct cs_info* get_current_cs(const char* es) {
|
|||
// XXX This function was rewritten for mozilla. Instead of storing the
|
||||
// conversion tables static in this file, create them when needed
|
||||
// with help the mozilla backend.
|
||||
struct cs_info* get_current_cs(const char* es) {
|
||||
struct cs_info* get_current_cs(const std::string& es) {
|
||||
struct cs_info* ccs = new cs_info[256];
|
||||
// Initialze the array with dummy data so that we wouldn't need
|
||||
// to return null in case of failures.
|
||||
|
@ -2500,7 +2308,7 @@ struct cs_info* get_current_cs(const char* es) {
|
|||
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString label(es);
|
||||
nsAutoCString label(es.c_str());
|
||||
nsAutoCString encoding;
|
||||
if (!EncodingUtils::FindEncodingForLabelNoReplacement(label, encoding)) {
|
||||
return ccs;
|
||||
|
@ -2565,21 +2373,18 @@ struct cs_info* get_current_cs(const char* es) {
|
|||
#endif
|
||||
|
||||
// primitive isalpha() replacement for tokenization
|
||||
char* get_casechars(const char* enc) {
|
||||
std::string get_casechars(const char* enc) {
|
||||
struct cs_info* csconv = get_current_cs(enc);
|
||||
char expw[MAXLNLEN];
|
||||
char* p = expw;
|
||||
for (int i = 0; i <= 255; i++) {
|
||||
std::string expw;
|
||||
for (int i = 0; i <= 255; ++i) {
|
||||
if (cupper(csconv, i) != clower(csconv, i)) {
|
||||
*p = static_cast<char>(i);
|
||||
p++;
|
||||
expw.push_back(static_cast<char>(i));
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
#ifdef MOZILLA_CLIENT
|
||||
delete[] csconv;
|
||||
#endif
|
||||
return mystrdup(expw);
|
||||
return expw;
|
||||
}
|
||||
|
||||
// language to encoding default map
|
||||
|
@ -2606,10 +2411,10 @@ static struct lang_map lang2enc[] =
|
|||
{"tr_TR", LANG_tr}, // for back-compatibility
|
||||
{"ru", LANG_ru}, {"uk", LANG_uk}};
|
||||
|
||||
int get_lang_num(const char* lang) {
|
||||
int get_lang_num(const std::string& lang) {
|
||||
int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (strcmp(lang, lang2enc[i].lang) == 0) {
|
||||
if (strcmp(lang.c_str(), lang2enc[i].lang) == 0) {
|
||||
return lang2enc[i].num;
|
||||
}
|
||||
}
|
||||
|
@ -2618,26 +2423,21 @@ int get_lang_num(const char* lang) {
|
|||
|
||||
#ifndef OPENOFFICEORG
|
||||
#ifndef MOZILLA_CLIENT
|
||||
int initialize_utf_tbl() {
|
||||
void initialize_utf_tbl() {
|
||||
utf_tbl_count++;
|
||||
if (utf_tbl)
|
||||
return 0;
|
||||
utf_tbl = (unicode_info2*)malloc(CONTSIZE * sizeof(unicode_info2));
|
||||
if (utf_tbl) {
|
||||
size_t j;
|
||||
for (j = 0; j < CONTSIZE; j++) {
|
||||
utf_tbl[j].cletter = 0;
|
||||
utf_tbl[j].clower = (unsigned short)j;
|
||||
utf_tbl[j].cupper = (unsigned short)j;
|
||||
}
|
||||
for (j = 0; j < UTF_LST_LEN; j++) {
|
||||
utf_tbl[utf_lst[j].c].cletter = 1;
|
||||
utf_tbl[utf_lst[j].c].clower = utf_lst[j].clower;
|
||||
utf_tbl[utf_lst[j].c].cupper = utf_lst[j].cupper;
|
||||
}
|
||||
} else
|
||||
return 1;
|
||||
return 0;
|
||||
return;
|
||||
utf_tbl = new unicode_info2[CONTSIZE];
|
||||
for (size_t j = 0; j < CONTSIZE; ++j) {
|
||||
utf_tbl[j].cletter = 0;
|
||||
utf_tbl[j].clower = (unsigned short)j;
|
||||
utf_tbl[j].cupper = (unsigned short)j;
|
||||
}
|
||||
for (size_t j = 0; j < UTF_LST_LEN; ++j) {
|
||||
utf_tbl[utf_lst[j].c].cletter = 1;
|
||||
utf_tbl[utf_lst[j].c].clower = utf_lst[j].clower;
|
||||
utf_tbl[utf_lst[j].c].cupper = utf_lst[j].cupper;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -2646,7 +2446,7 @@ void free_utf_tbl() {
|
|||
if (utf_tbl_count > 0)
|
||||
utf_tbl_count--;
|
||||
if (utf_tbl && (utf_tbl_count == 0)) {
|
||||
free(utf_tbl);
|
||||
delete[] utf_tbl;
|
||||
utf_tbl = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -2775,18 +2575,6 @@ size_t remove_ignored_chars_utf(std::string& word,
|
|||
return w2.size();
|
||||
}
|
||||
|
||||
namespace {
|
||||
class is_any_of {
|
||||
public:
|
||||
is_any_of(const std::string& in) : chars(in) {}
|
||||
|
||||
bool operator()(char c) { return chars.find(c) != std::string::npos; }
|
||||
|
||||
private:
|
||||
std::string chars;
|
||||
};
|
||||
}
|
||||
|
||||
// strip all ignored characters in the string
|
||||
size_t remove_ignored_chars(std::string& word,
|
||||
const std::string& ignored_chars) {
|
||||
|
@ -2796,54 +2584,48 @@ size_t remove_ignored_chars(std::string& word,
|
|||
return word.size();
|
||||
}
|
||||
|
||||
int parse_string(char* line, char** out, int ln) {
|
||||
char* tp = line;
|
||||
char* piece;
|
||||
bool parse_string(const std::string& line, std::string& out, int ln) {
|
||||
if (!out.empty()) {
|
||||
HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions\n", ln);
|
||||
return false;
|
||||
}
|
||||
int i = 0;
|
||||
int np = 0;
|
||||
if (*out) {
|
||||
HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions\n", ln);
|
||||
return 1;
|
||||
}
|
||||
piece = mystrsep(&tp, 0);
|
||||
while (piece) {
|
||||
if (*piece != '\0') {
|
||||
switch (i) {
|
||||
case 0: {
|
||||
np++;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
*out = mystrdup(piece);
|
||||
if (!*out)
|
||||
return 1;
|
||||
np++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
std::string::const_iterator iter = line.begin();
|
||||
std::string::const_iterator start_piece = mystrsep(line, iter);
|
||||
while (start_piece != line.end()) {
|
||||
switch (i) {
|
||||
case 0: {
|
||||
np++;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
case 1: {
|
||||
out.assign(start_piece, iter);
|
||||
np++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// free(piece);
|
||||
piece = mystrsep(&tp, 0);
|
||||
++i;
|
||||
start_piece = mystrsep(line, iter);
|
||||
}
|
||||
if (np != 2) {
|
||||
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", ln);
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_array(char* line,
|
||||
char** out,
|
||||
bool parse_array(const std::string& line,
|
||||
std::string& out,
|
||||
std::vector<w_char>& out_utf16,
|
||||
int utf8,
|
||||
int ln) {
|
||||
if (parse_string(line, out, ln))
|
||||
if (!parse_string(line, out, ln))
|
||||
return false;
|
||||
if (utf8) {
|
||||
u8_u16(out_utf16, *out);
|
||||
u8_u16(out_utf16, out);
|
||||
std::sort(out_utf16.begin(), out_utf16.end());
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -71,13 +71,14 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __CSUTILHXX__
|
||||
#define __CSUTILHXX__
|
||||
#ifndef CSUTIL_HXX_
|
||||
#define CSUTIL_HXX_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
|
||||
// First some base level utility routines
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
|
@ -127,8 +128,9 @@
|
|||
#define FORBIDDENWORD 65510
|
||||
#define ONLYUPCASEFLAG 65511
|
||||
|
||||
// fopen or optional _wfopen to fix long pathname problem of WIN32
|
||||
LIBHUNSPELL_DLL_EXPORTED FILE* myfopen(const char* path, const char* mode);
|
||||
// fix long pathname problem of WIN32 by using w_char std::fstream::open override
|
||||
LIBHUNSPELL_DLL_EXPORTED void myopen(std::ifstream& stream, const char* path,
|
||||
std::ios_base::openmode mode);
|
||||
|
||||
// convert UTF-16 characters to UTF-8
|
||||
LIBHUNSPELL_DLL_EXPORTED std::string& u16_u8(std::string& dest,
|
||||
|
@ -139,21 +141,16 @@ LIBHUNSPELL_DLL_EXPORTED int u8_u16(std::vector<w_char>& dest,
|
|||
const std::string& src);
|
||||
|
||||
// remove end of line char(s)
|
||||
LIBHUNSPELL_DLL_EXPORTED void mychomp(char* s);
|
||||
LIBHUNSPELL_DLL_EXPORTED void mychomp(std::string& s);
|
||||
|
||||
// duplicate string
|
||||
LIBHUNSPELL_DLL_EXPORTED char* mystrdup(const char* s);
|
||||
|
||||
// strcat for limited length destination string
|
||||
LIBHUNSPELL_DLL_EXPORTED char* mystrcat(char* dest, const char* st, int max);
|
||||
|
||||
// parse into tokens with char delimiter
|
||||
LIBHUNSPELL_DLL_EXPORTED char* mystrsep(char** sptr, const char delim);
|
||||
LIBHUNSPELL_DLL_EXPORTED std::string::const_iterator mystrsep(const std::string &str,
|
||||
std::string::const_iterator& start);
|
||||
|
||||
// replace pat by rep in word and return word
|
||||
LIBHUNSPELL_DLL_EXPORTED char* mystrrep(char* word,
|
||||
const char* pat,
|
||||
const char* rep);
|
||||
LIBHUNSPELL_DLL_EXPORTED std::string& mystrrep(std::string& str,
|
||||
const std::string& search,
|
||||
const std::string& replace);
|
||||
|
@ -163,13 +160,13 @@ LIBHUNSPELL_DLL_EXPORTED std::string& strlinecat(std::string& str,
|
|||
const std::string& apd);
|
||||
|
||||
// tokenize into lines with new line
|
||||
LIBHUNSPELL_DLL_EXPORTED int line_tok(const char* text,
|
||||
char*** lines,
|
||||
char breakchar);
|
||||
LIBHUNSPELL_DLL_EXPORTED std::vector<std::string> line_tok(const std::string& text,
|
||||
char breakchar);
|
||||
|
||||
// tokenize into lines with new line and uniq in place
|
||||
LIBHUNSPELL_DLL_EXPORTED char* line_uniq(char* text, char breakchar);
|
||||
LIBHUNSPELL_DLL_EXPORTED char* line_uniq_app(char** text, char breakchar);
|
||||
LIBHUNSPELL_DLL_EXPORTED void line_uniq(std::string& text, char breakchar);
|
||||
|
||||
LIBHUNSPELL_DLL_EXPORTED void line_uniq_app(std::string& text, char breakchar);
|
||||
|
||||
// reverse word
|
||||
LIBHUNSPELL_DLL_EXPORTED size_t reverseword(std::string& word);
|
||||
|
@ -178,10 +175,7 @@ LIBHUNSPELL_DLL_EXPORTED size_t reverseword(std::string& word);
|
|||
LIBHUNSPELL_DLL_EXPORTED size_t reverseword_utf(std::string&);
|
||||
|
||||
// remove duplicates
|
||||
LIBHUNSPELL_DLL_EXPORTED int uniqlist(char** list, int n);
|
||||
|
||||
// free character array list
|
||||
LIBHUNSPELL_DLL_EXPORTED void freelist(char*** list, int n);
|
||||
LIBHUNSPELL_DLL_EXPORTED void uniqlist(std::vector<std::string>& list);
|
||||
|
||||
// character encoding information
|
||||
struct cs_info {
|
||||
|
@ -190,7 +184,7 @@ struct cs_info {
|
|||
unsigned char cupper;
|
||||
};
|
||||
|
||||
LIBHUNSPELL_DLL_EXPORTED int initialize_utf_tbl();
|
||||
LIBHUNSPELL_DLL_EXPORTED void initialize_utf_tbl();
|
||||
LIBHUNSPELL_DLL_EXPORTED void free_utf_tbl();
|
||||
LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetoupper(unsigned short c,
|
||||
int langnum);
|
||||
|
@ -200,13 +194,13 @@ LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetolower(unsigned short c,
|
|||
int langnum);
|
||||
LIBHUNSPELL_DLL_EXPORTED int unicodeisalpha(unsigned short c);
|
||||
|
||||
LIBHUNSPELL_DLL_EXPORTED struct cs_info* get_current_cs(const char* es);
|
||||
LIBHUNSPELL_DLL_EXPORTED struct cs_info* get_current_cs(const std::string& es);
|
||||
|
||||
// get language identifiers of language codes
|
||||
LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const char* lang);
|
||||
LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const std::string& lang);
|
||||
|
||||
// get characters of the given 8bit encoding with lower- and uppercase forms
|
||||
LIBHUNSPELL_DLL_EXPORTED char* get_casechars(const char* enc);
|
||||
LIBHUNSPELL_DLL_EXPORTED std::string get_casechars(const char* enc);
|
||||
|
||||
// convert std::string to all caps
|
||||
LIBHUNSPELL_DLL_EXPORTED std::string& mkallcap(std::string& s,
|
||||
|
@ -256,10 +250,12 @@ LIBHUNSPELL_DLL_EXPORTED size_t remove_ignored_chars(
|
|||
std::string& word,
|
||||
const std::string& ignored_chars);
|
||||
|
||||
LIBHUNSPELL_DLL_EXPORTED int parse_string(char* line, char** out, int ln);
|
||||
LIBHUNSPELL_DLL_EXPORTED bool parse_string(const std::string& line,
|
||||
std::string& out,
|
||||
int ln);
|
||||
|
||||
LIBHUNSPELL_DLL_EXPORTED bool parse_array(char* line,
|
||||
char** out,
|
||||
LIBHUNSPELL_DLL_EXPORTED bool parse_array(const std::string& line,
|
||||
std::string& out,
|
||||
std::vector<w_char>& out_utf16,
|
||||
int utf8,
|
||||
int ln);
|
||||
|
@ -270,10 +266,6 @@ LIBHUNSPELL_DLL_EXPORTED bool copy_field(std::string& dest,
|
|||
const std::string& morph,
|
||||
const std::string& var);
|
||||
|
||||
LIBHUNSPELL_DLL_EXPORTED int morphcmp(const char* s, const char* t);
|
||||
|
||||
LIBHUNSPELL_DLL_EXPORTED int get_sfxcount(const char* morph);
|
||||
|
||||
// conversion function for protected memory
|
||||
LIBHUNSPELL_DLL_EXPORTED void store_pointer(char* dest, char* source);
|
||||
|
||||
|
|
|
@ -86,33 +86,33 @@ int FileMgr::fail(const char* err, const char* par) {
|
|||
FileMgr::FileMgr(const char* file, const char* key) : hin(NULL), linenum(0) {
|
||||
in[0] = '\0';
|
||||
|
||||
fin = myfopen(file, "r");
|
||||
if (!fin) {
|
||||
myopen(fin, file, std::ios_base::in);
|
||||
if (!fin.is_open()) {
|
||||
// check hzipped file
|
||||
std::string st(file);
|
||||
st.append(HZIP_EXTENSION);
|
||||
hin = new Hunzip(st.c_str(), key);
|
||||
}
|
||||
if (!fin && !hin)
|
||||
if (!fin.is_open() && !hin->is_open())
|
||||
fail(MSG_OPEN, file);
|
||||
}
|
||||
|
||||
FileMgr::~FileMgr() {
|
||||
if (fin)
|
||||
fclose(fin);
|
||||
if (hin)
|
||||
delete hin;
|
||||
delete hin;
|
||||
}
|
||||
|
||||
char* FileMgr::getline() {
|
||||
const char* l;
|
||||
linenum++;
|
||||
if (fin)
|
||||
return fgets(in, BUFSIZE - 1, fin);
|
||||
if (hin && ((l = hin->getline()) != NULL))
|
||||
return strcpy(in, l);
|
||||
linenum--;
|
||||
return NULL;
|
||||
bool FileMgr::getline(std::string& dest) {
|
||||
bool ret = false;
|
||||
++linenum;
|
||||
if (fin.is_open()) {
|
||||
ret = static_cast<bool>(std::getline(fin, dest));
|
||||
} else if (hin->is_open()) {
|
||||
ret = hin->getline(dest);
|
||||
}
|
||||
if (!ret) {
|
||||
--linenum;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int FileMgr::getlinenum() {
|
||||
|
|
|
@ -72,21 +72,21 @@
|
|||
*/
|
||||
|
||||
/* file manager class - read lines of files [filename] OR [filename.hz] */
|
||||
#ifndef _FILEMGR_HXX_
|
||||
#define _FILEMGR_HXX_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
#ifndef FILEMGR_HXX_
|
||||
#define FILEMGR_HXX_
|
||||
|
||||
#include "hunzip.hxx"
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
class LIBHUNSPELL_DLL_EXPORTED FileMgr {
|
||||
class FileMgr {
|
||||
private:
|
||||
FileMgr(const FileMgr&);
|
||||
FileMgr& operator=(const FileMgr&);
|
||||
|
||||
protected:
|
||||
FILE* fin;
|
||||
std::ifstream fin;
|
||||
Hunzip* hin;
|
||||
char in[BUFSIZE + 50]; // input buffer
|
||||
int fail(const char* err, const char* par);
|
||||
|
@ -95,7 +95,7 @@ class LIBHUNSPELL_DLL_EXPORTED FileMgr {
|
|||
public:
|
||||
FileMgr(const char* filename, const char* key = NULL);
|
||||
~FileMgr();
|
||||
char* getline();
|
||||
bool getline(std::string&);
|
||||
int getlinenum();
|
||||
};
|
||||
#endif
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -71,10 +71,8 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _HASHMGR_HXX_
|
||||
#define _HASHMGR_HXX_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
#ifndef HASHMGR_HXX_
|
||||
#define HASHMGR_HXX_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
@ -86,7 +84,7 @@
|
|||
|
||||
enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI };
|
||||
|
||||
class LIBHUNSPELL_DLL_EXPORTED HashMgr {
|
||||
class HashMgr {
|
||||
int tablesize;
|
||||
struct hentry** tableptr;
|
||||
flag flag_mode;
|
||||
|
@ -94,10 +92,10 @@ class LIBHUNSPELL_DLL_EXPORTED HashMgr {
|
|||
int utf8;
|
||||
unsigned short forbiddenword;
|
||||
int langnum;
|
||||
char* enc;
|
||||
char* lang;
|
||||
std::string enc;
|
||||
std::string lang;
|
||||
struct cs_info* csconv;
|
||||
char* ignorechars;
|
||||
std::string ignorechars;
|
||||
std::vector<w_char> ignorechars_utf16;
|
||||
int numaliasf; // flag vector `compression' with aliases
|
||||
unsigned short** aliasf;
|
||||
|
@ -114,35 +112,35 @@ class LIBHUNSPELL_DLL_EXPORTED HashMgr {
|
|||
struct hentry* walk_hashtable(int& col, struct hentry* hp) const;
|
||||
|
||||
int add(const std::string& word);
|
||||
int add_with_affix(const char* word, const char* pattern);
|
||||
int remove(const char* word);
|
||||
int decode_flags(unsigned short** result, char* flags, FileMgr* af);
|
||||
unsigned short decode_flag(const char* flag);
|
||||
char* encode_flag(unsigned short flag);
|
||||
int is_aliasf();
|
||||
int get_aliasf(int index, unsigned short** fvec, FileMgr* af);
|
||||
int is_aliasm();
|
||||
char* get_aliasm(int index);
|
||||
int add_with_affix(const std::string& word, const std::string& pattern);
|
||||
int remove(const std::string& word);
|
||||
int decode_flags(unsigned short** result, const std::string& flags, FileMgr* af) const;
|
||||
bool decode_flags(std::vector<unsigned short>& result, const std::string& flags, FileMgr* af) const;
|
||||
unsigned short decode_flag(const char* flag) const;
|
||||
char* encode_flag(unsigned short flag) const;
|
||||
int is_aliasf() const;
|
||||
int get_aliasf(int index, unsigned short** fvec, FileMgr* af) const;
|
||||
int is_aliasm() const;
|
||||
char* get_aliasm(int index) const;
|
||||
|
||||
private:
|
||||
int get_clen_and_captype(const std::string& word, int* captype);
|
||||
int load_tables(const char* tpath, const char* key);
|
||||
int add_word(const char* word,
|
||||
int wbl,
|
||||
int add_word(const std::string& word,
|
||||
int wcl,
|
||||
unsigned short* ap,
|
||||
int al,
|
||||
const char* desc,
|
||||
const std::string* desc,
|
||||
bool onlyupcase);
|
||||
int load_config(const char* affpath, const char* key);
|
||||
int parse_aliasf(char* line, FileMgr* af);
|
||||
bool parse_aliasf(const std::string& line, FileMgr* af);
|
||||
int add_hidden_capitalized_word(const std::string& word,
|
||||
int wcl,
|
||||
unsigned short* flags,
|
||||
int al,
|
||||
char* dp,
|
||||
const std::string* dp,
|
||||
int captype);
|
||||
int parse_aliasm(char* line, FileMgr* af);
|
||||
bool parse_aliasm(const std::string& line, FileMgr* af);
|
||||
int remove_forbidden_flag(const std::string& word);
|
||||
};
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _HTYPES_HXX_
|
||||
#define _HTYPES_HXX_
|
||||
#ifndef HTYPES_HXX_
|
||||
#define HTYPES_HXX_
|
||||
|
||||
#define ROTATE_LEN 5
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -38,8 +38,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _MYSPELLMGR_H_
|
||||
#define _MYSPELLMGR_H_
|
||||
#ifndef MYSPELLMGR_H_
|
||||
#define MYSPELLMGR_H_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
|
||||
|
|
|
@ -70,26 +70,30 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef MYSPELLMGR_HXX_
|
||||
#define MYSPELLMGR_HXX_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
|
||||
#include "hashmgr.hxx"
|
||||
#include "affixmgr.hxx"
|
||||
#include "suggestmgr.hxx"
|
||||
#include "langnum.hxx"
|
||||
#include "w_char.hxx"
|
||||
#include "atypes.hxx"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define SPELL_XML "<?xml?>"
|
||||
|
||||
#define MAXDIC 20
|
||||
#define MAXSUGGESTION 15
|
||||
#define MAXSHARPS 5
|
||||
#define MAXWORDLEN 176
|
||||
|
||||
#define HUNSPELL_OK (1 << 0)
|
||||
#define HUNSPELL_OK_WARN (1 << 1)
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
|
||||
# define H_DEPRECATED __attribute__((__deprecated__))
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
# define H_DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
# define H_DEPRECATED
|
||||
#endif
|
||||
|
||||
#ifndef _MYSPELLMGR_HXX_
|
||||
#define _MYSPELLMGR_HXX_
|
||||
class HunspellImpl;
|
||||
|
||||
class LIBHUNSPELL_DLL_EXPORTED Hunspell {
|
||||
private:
|
||||
|
@ -97,17 +101,7 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
|
|||
Hunspell& operator=(const Hunspell&);
|
||||
|
||||
private:
|
||||
AffixMgr* pAMgr;
|
||||
HashMgr* pHMgr[MAXDIC];
|
||||
int maxdic;
|
||||
SuggestMgr* pSMgr;
|
||||
char* affixpath;
|
||||
char* encoding;
|
||||
struct cs_info* csconv;
|
||||
int langnum;
|
||||
int utf8;
|
||||
int complexprefixes;
|
||||
char** wordbreak;
|
||||
HunspellImpl* m_Impl;
|
||||
|
||||
public:
|
||||
/* Hunspell(aff, dic) - constructor of Hunspell class
|
||||
|
@ -118,7 +112,6 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
|
|||
* long path names (without the long path prefix Hunspell will use fopen()
|
||||
* with system-dependent character encoding instead of _wfopen()).
|
||||
*/
|
||||
|
||||
Hunspell(const char* affpath, const char* dpath, const char* key = NULL);
|
||||
~Hunspell();
|
||||
|
||||
|
@ -126,7 +119,7 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
|
|||
int add_dic(const char* dpath, const char* key = NULL);
|
||||
|
||||
/* spell(word) - spellcheck word
|
||||
* output: 0 = bad word, not 0 = good word
|
||||
* output: false = bad word, true = good word
|
||||
*
|
||||
* plus output:
|
||||
* info: information bit array, fields:
|
||||
|
@ -134,8 +127,8 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
|
|||
* SPELL_FORBIDDEN = an explicit forbidden word
|
||||
* root: root (stem), when input is a word with affix(es)
|
||||
*/
|
||||
|
||||
int spell(const char* word, int* info = NULL, char** root = NULL);
|
||||
bool spell(const std::string& word, int* info = NULL, std::string* root = NULL);
|
||||
H_DEPRECATED int spell(const char* word, int* info = NULL, char** root = NULL);
|
||||
|
||||
/* suggest(suggestions, word) - search suggestions
|
||||
* input: pointer to an array of strings pointer and the (bad) word
|
||||
|
@ -144,8 +137,8 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
|
|||
* a newly allocated array of strings (*slts will be NULL when number
|
||||
* of suggestion equals 0.)
|
||||
*/
|
||||
|
||||
int suggest(char*** slst, const char* word);
|
||||
std::vector<std::string> suggest(const std::string& word);
|
||||
H_DEPRECATED int suggest(char*** slst, const char* word);
|
||||
|
||||
/* Suggest words from suffix rules
|
||||
* suffix_suggest(suggestions, root_word)
|
||||
|
@ -155,36 +148,37 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
|
|||
* a newly allocated array of strings (*slts will be NULL when number
|
||||
* of suggestion equals 0.)
|
||||
*/
|
||||
int suffix_suggest(char*** slst, const char* root_word);
|
||||
std::vector<std::string> suffix_suggest(const std::string& root_word);
|
||||
H_DEPRECATED int suffix_suggest(char*** slst, const char* root_word);
|
||||
|
||||
/* deallocate suggestion lists */
|
||||
H_DEPRECATED void free_list(char*** slst, int n);
|
||||
|
||||
void free_list(char*** slst, int n);
|
||||
|
||||
const std::string& get_dict_encoding() const;
|
||||
char* get_dic_encoding();
|
||||
|
||||
/* morphological functions */
|
||||
|
||||
/* analyze(result, word) - morphological analysis of the word */
|
||||
std::vector<std::string> analyze(const std::string& word);
|
||||
H_DEPRECATED int analyze(char*** slst, const char* word);
|
||||
|
||||
int analyze(char*** slst, const char* word);
|
||||
/* stem(word) - stemmer function */
|
||||
std::vector<std::string> stem(const std::string& word);
|
||||
H_DEPRECATED int stem(char*** slst, const char* word);
|
||||
|
||||
/* stem(result, word) - stemmer function */
|
||||
|
||||
int stem(char*** slst, const char* word);
|
||||
|
||||
/* stem(result, analysis, n) - get stems from a morph. analysis
|
||||
/* stem(analysis, n) - get stems from a morph. analysis
|
||||
* example:
|
||||
* char ** result, result2;
|
||||
* int n1 = analyze(&result, "words");
|
||||
* int n2 = stem(&result2, result, n1);
|
||||
*/
|
||||
|
||||
int stem(char*** slst, char** morph, int n);
|
||||
std::vector<std::string> stem(const std::vector<std::string>& morph);
|
||||
H_DEPRECATED int stem(char*** slst, char** morph, int n);
|
||||
|
||||
/* generate(result, word, word2) - morphological generation by example(s) */
|
||||
|
||||
int generate(char*** slst, const char* word, const char* word2);
|
||||
std::vector<std::string> generate(const std::string& word, const std::string& word2);
|
||||
H_DEPRECATED int generate(char*** slst, const char* word, const char* word2);
|
||||
|
||||
/* generate(result, word, desc, n) - generation by morph. description(s)
|
||||
* example:
|
||||
|
@ -193,66 +187,43 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
|
|||
* int n = generate(&result, "word", &affix, 1);
|
||||
* for (int i = 0; i < n; i++) printf("%s\n", result[i]);
|
||||
*/
|
||||
|
||||
int generate(char*** slst, const char* word, char** desc, int n);
|
||||
std::vector<std::string> generate(const std::string& word, const std::vector<std::string>& pl);
|
||||
H_DEPRECATED int generate(char*** slst, const char* word, char** desc, int n);
|
||||
|
||||
/* functions for run-time modification of the dictionary */
|
||||
|
||||
/* add word to the run-time dictionary */
|
||||
|
||||
int add(const char* word);
|
||||
int add(const std::string& word);
|
||||
|
||||
/* add word to the run-time dictionary with affix flags of
|
||||
* the example (a dictionary word): Hunspell will recognize
|
||||
* affixed forms of the new word, too.
|
||||
*/
|
||||
|
||||
int add_with_affix(const char* word, const char* example);
|
||||
int add_with_affix(const std::string& word, const std::string& example);
|
||||
|
||||
/* remove word from the run-time dictionary */
|
||||
|
||||
int remove(const char* word);
|
||||
int remove(const std::string& word);
|
||||
|
||||
/* other */
|
||||
|
||||
/* get extra word characters definied in affix file for tokenization */
|
||||
const char* get_wordchars();
|
||||
const std::vector<w_char>& get_wordchars_utf16();
|
||||
const char* get_wordchars() const;
|
||||
const std::string& get_wordchars_cpp() const;
|
||||
const std::vector<w_char>& get_wordchars_utf16() const;
|
||||
|
||||
struct cs_info* get_csconv();
|
||||
const char* get_version();
|
||||
|
||||
const char* get_version() const;
|
||||
const std::string& get_version_cpp() const;
|
||||
|
||||
int get_langnum() const;
|
||||
|
||||
/* need for putdic */
|
||||
int input_conv(const char* word, char* dest, size_t destsize);
|
||||
|
||||
private:
|
||||
void cleanword(std::string& dest, const char*, int* pcaptype, int* pabbrev);
|
||||
size_t cleanword2(std::string& dest,
|
||||
std::vector<w_char>& dest_u,
|
||||
const char*,
|
||||
int* w_len,
|
||||
int* pcaptype,
|
||||
size_t* pabbrev);
|
||||
void mkinitcap(std::string& u8);
|
||||
int mkinitcap2(std::string& u8, std::vector<w_char>& u16);
|
||||
int mkinitsmall2(std::string& u8, std::vector<w_char>& u16);
|
||||
void mkallcap(std::string& u8);
|
||||
int mkallsmall2(std::string& u8, std::vector<w_char>& u16);
|
||||
struct hentry* checkword(const char*, int* info, char** root);
|
||||
std::string sharps_u8_l1(const std::string& source);
|
||||
hentry*
|
||||
spellsharps(std::string& base, size_t start_pos, int, int, int* info, char** root);
|
||||
int is_keepcase(const hentry* rv);
|
||||
int insert_sug(char*** slst, const char* word, int ns);
|
||||
void cat_result(std::string& result, char* st);
|
||||
char* stem_description(const char* desc);
|
||||
int spellml(char*** slst, const char* word);
|
||||
std::string get_xml_par(const char* par);
|
||||
const char* get_xml_pos(const char* s, const char* attr);
|
||||
int get_xml_list(char*** slst, const char* list, const char* tag);
|
||||
int check_xml_par(const char* q, const char* attr, const char* value);
|
||||
bool input_conv(const std::string& word, std::string& dest);
|
||||
H_DEPRECATED int input_conv(const char* word, char* dest, size_t destsize);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef _HUNSPELL_VISIBILITY_H_
|
||||
#define _HUNSPELL_VISIBILITY_H_
|
||||
#ifndef HUNSPELL_VISIBILITY_H_
|
||||
#define HUNSPELL_VISIBILITY_H_
|
||||
|
||||
#if defined(HUNSPELL_STATIC)
|
||||
# define LIBHUNSPELL_DLL_EXPORTED
|
||||
|
|
|
@ -59,7 +59,7 @@ int Hunzip::fail(const char* err, const char* par) {
|
|||
}
|
||||
|
||||
Hunzip::Hunzip(const char* file, const char* key)
|
||||
: fin(NULL), bufsiz(0), lastbit(0), inc(0), inbits(0), outc(0), dec(NULL) {
|
||||
: bufsiz(0), lastbit(0), inc(0), inbits(0), outc(0) {
|
||||
in[0] = out[0] = line[0] = '\0';
|
||||
filename = mystrdup(file);
|
||||
if (getcode(key) == -1)
|
||||
|
@ -70,19 +70,19 @@ Hunzip::Hunzip(const char* file, const char* key)
|
|||
|
||||
int Hunzip::getcode(const char* key) {
|
||||
unsigned char c[2];
|
||||
int i, j, n, p;
|
||||
int i, j, n;
|
||||
int allocatedbit = BASEBITREC;
|
||||
const char* enc = key;
|
||||
|
||||
if (!filename)
|
||||
return -1;
|
||||
|
||||
fin = myfopen(filename, "rb");
|
||||
if (!fin)
|
||||
myopen(fin, filename, std::ios_base::in | std::ios_base::binary);
|
||||
if (!fin.is_open())
|
||||
return -1;
|
||||
|
||||
// read magic number
|
||||
if ((fread(in, 1, 3, fin) < MAGICLEN) ||
|
||||
if (!fin.read(in, 3) ||
|
||||
!(strncmp(MAGIC, in, MAGICLEN) == 0 ||
|
||||
strncmp(MAGIC_ENCRYPT, in, MAGICLEN) == 0)) {
|
||||
return fail(MSG_FORMAT, filename);
|
||||
|
@ -93,7 +93,7 @@ int Hunzip::getcode(const char* key) {
|
|||
unsigned char cs;
|
||||
if (!key)
|
||||
return fail(MSG_KEY, filename);
|
||||
if (fread(&c, 1, 1, fin) < 1)
|
||||
if (!fin.read(reinterpret_cast<char*>(c), 1))
|
||||
return fail(MSG_FORMAT, filename);
|
||||
for (cs = 0; *enc; enc++)
|
||||
cs ^= *enc;
|
||||
|
@ -104,7 +104,7 @@ int Hunzip::getcode(const char* key) {
|
|||
key = NULL;
|
||||
|
||||
// read record count
|
||||
if (fread(&c, 1, 2, fin) < 2)
|
||||
if (!fin.read(reinterpret_cast<char*>(c), 2))
|
||||
return fail(MSG_FORMAT, filename);
|
||||
|
||||
if (key) {
|
||||
|
@ -115,16 +115,14 @@ int Hunzip::getcode(const char* key) {
|
|||
}
|
||||
|
||||
n = ((int)c[0] << 8) + c[1];
|
||||
dec = (struct bit*)malloc(BASEBITREC * sizeof(struct bit));
|
||||
if (!dec)
|
||||
return fail(MSG_MEMORY, filename);
|
||||
dec.resize(BASEBITREC);
|
||||
dec[0].v[0] = 0;
|
||||
dec[0].v[1] = 0;
|
||||
|
||||
// read codes
|
||||
for (i = 0; i < n; i++) {
|
||||
unsigned char l;
|
||||
if (fread(c, 1, 2, fin) < 2)
|
||||
if (!fin.read(reinterpret_cast<char*>(c), 2))
|
||||
return fail(MSG_FORMAT, filename);
|
||||
if (key) {
|
||||
if (*(++enc) == '\0')
|
||||
|
@ -134,14 +132,14 @@ int Hunzip::getcode(const char* key) {
|
|||
enc = key;
|
||||
c[1] ^= *enc;
|
||||
}
|
||||
if (fread(&l, 1, 1, fin) < 1)
|
||||
if (!fin.read(reinterpret_cast<char*>(&l), 1))
|
||||
return fail(MSG_FORMAT, filename);
|
||||
if (key) {
|
||||
if (*(++enc) == '\0')
|
||||
enc = key;
|
||||
l ^= *enc;
|
||||
}
|
||||
if (fread(in, 1, l / 8 + 1, fin) < (size_t)l / 8 + 1)
|
||||
if (!fin.read(in, l / 8 + 1))
|
||||
return fail(MSG_FORMAT, filename);
|
||||
if (key)
|
||||
for (j = 0; j <= l / 8; j++) {
|
||||
|
@ -149,7 +147,7 @@ int Hunzip::getcode(const char* key) {
|
|||
enc = key;
|
||||
in[j] ^= *enc;
|
||||
}
|
||||
p = 0;
|
||||
int p = 0;
|
||||
for (j = 0; j < l; j++) {
|
||||
int b = (in[j / 8] & (1 << (7 - (j % 8)))) ? 1 : 0;
|
||||
int oldp = p;
|
||||
|
@ -158,7 +156,7 @@ int Hunzip::getcode(const char* key) {
|
|||
lastbit++;
|
||||
if (lastbit == allocatedbit) {
|
||||
allocatedbit += BASEBITREC;
|
||||
dec = (struct bit*)realloc(dec, allocatedbit * sizeof(struct bit));
|
||||
dec.resize(allocatedbit);
|
||||
}
|
||||
dec[lastbit].v[0] = 0;
|
||||
dec[lastbit].v[1] = 0;
|
||||
|
@ -173,10 +171,6 @@ int Hunzip::getcode(const char* key) {
|
|||
}
|
||||
|
||||
Hunzip::~Hunzip() {
|
||||
if (dec)
|
||||
free(dec);
|
||||
if (fin)
|
||||
fclose(fin);
|
||||
if (filename)
|
||||
free(filename);
|
||||
}
|
||||
|
@ -185,16 +179,17 @@ int Hunzip::getbuf() {
|
|||
int p = 0;
|
||||
int o = 0;
|
||||
do {
|
||||
if (inc == 0)
|
||||
inbits = fread(in, 1, BUFSIZE, fin) * 8;
|
||||
if (inc == 0) {
|
||||
fin.read(in, BUFSIZE);
|
||||
inbits = fin.gcount() * 8;
|
||||
}
|
||||
for (; inc < inbits; inc++) {
|
||||
int b = (in[inc / 8] & (1 << (7 - (inc % 8)))) ? 1 : 0;
|
||||
int oldp = p;
|
||||
p = dec[p].v[b];
|
||||
if (p == 0) {
|
||||
if (oldp == lastbit) {
|
||||
fclose(fin);
|
||||
fin = NULL;
|
||||
fin.close();
|
||||
// add last odd byte
|
||||
if (dec[lastbit].c[0])
|
||||
out[o++] = dec[lastbit].c[1];
|
||||
|
@ -212,11 +207,11 @@ int Hunzip::getbuf() {
|
|||
return fail(MSG_FORMAT, filename);
|
||||
}
|
||||
|
||||
const char* Hunzip::getline() {
|
||||
bool Hunzip::getline(std::string& dest) {
|
||||
char linebuf[BUFSIZE];
|
||||
int l = 0, eol = 0, left = 0, right = 0;
|
||||
if (bufsiz == -1)
|
||||
return NULL;
|
||||
return false;
|
||||
while (l < bufsiz && !eol) {
|
||||
linebuf[l++] = out[outc];
|
||||
switch (out[outc]) {
|
||||
|
@ -251,7 +246,7 @@ const char* Hunzip::getline() {
|
|||
}
|
||||
if (++outc == bufsiz) {
|
||||
outc = 0;
|
||||
bufsiz = fin ? getbuf() : -1;
|
||||
bufsiz = fin.is_open() ? getbuf() : -1;
|
||||
}
|
||||
}
|
||||
if (right)
|
||||
|
@ -259,5 +254,6 @@ const char* Hunzip::getline() {
|
|||
else
|
||||
linebuf[l] = '\0';
|
||||
strcpy(line + left, linebuf);
|
||||
return line;
|
||||
dest.assign(line);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -41,12 +41,14 @@
|
|||
/* hunzip: file decompression for sorted dictionaries with optional encryption,
|
||||
* algorithm: prefix-suffix encoding and 16-bit Huffman encoding */
|
||||
|
||||
#ifndef _HUNZIP_HXX_
|
||||
#define _HUNZIP_HXX_
|
||||
#ifndef HUNZIP_HXX_
|
||||
#define HUNZIP_HXX_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#define BUFSIZE 65536
|
||||
#define HZIP_EXTENSION ".hz"
|
||||
|
@ -68,9 +70,9 @@ class LIBHUNSPELL_DLL_EXPORTED Hunzip {
|
|||
|
||||
protected:
|
||||
char* filename;
|
||||
FILE* fin;
|
||||
std::ifstream fin;
|
||||
int bufsiz, lastbit, inc, inbits, outc;
|
||||
struct bit* dec; // code table
|
||||
std::vector<bit> dec; // code table
|
||||
char in[BUFSIZE]; // input buffer
|
||||
char out[BUFSIZE + 1]; // Huffman-decoded buffer
|
||||
char line[BUFSIZE + 50]; // decoded line
|
||||
|
@ -81,7 +83,8 @@ class LIBHUNSPELL_DLL_EXPORTED Hunzip {
|
|||
public:
|
||||
Hunzip(const char* filename, const char* key = NULL);
|
||||
~Hunzip();
|
||||
const char* getline();
|
||||
bool is_open() { return fin.is_open(); }
|
||||
bool getline(std::string& dest);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,12 +38,12 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _LANGNUM_HXX_
|
||||
#define _LANGNUM_HXX_
|
||||
#ifndef LANGNUM_HXX_
|
||||
#define LANGNUM_HXX_
|
||||
|
||||
/*
|
||||
language numbers for language specific codes
|
||||
see http://l10n.openoffice.org/languages.html
|
||||
see https://wiki.openoffice.org/w/index.php?title=Languages&oldid=230199
|
||||
*/
|
||||
|
||||
enum {
|
||||
|
|
|
@ -36,15 +36,13 @@
|
|||
#include "phonet.hxx"
|
||||
|
||||
void init_phonet_hash(phonetable& parms) {
|
||||
int i, k;
|
||||
|
||||
for (i = 0; i < HASHSIZE; i++) {
|
||||
for (int i = 0; i < HASHSIZE; i++) {
|
||||
parms.hash[i] = -1;
|
||||
}
|
||||
|
||||
for (i = 0; parms.rules[i][0] != '\0'; i += 2) {
|
||||
for (int i = 0; parms.rules[i][0] != '\0'; i += 2) {
|
||||
/** set hash value **/
|
||||
k = (unsigned char)parms.rules[i][0];
|
||||
int k = (unsigned char)parms.rules[i][0];
|
||||
|
||||
if (parms.hash[k] < 0) {
|
||||
parms.hash[k] = i;
|
||||
|
@ -73,9 +71,8 @@ static int myisalpha(char ch) {
|
|||
std::string phonet(const std::string& inword, phonetable& parms) {
|
||||
|
||||
int i, k = 0, p, z;
|
||||
int k0, n0, p0 = -333, z0;
|
||||
int k0, n0, p0 = -333;
|
||||
char c;
|
||||
const char* s;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
size_t len = inword.size();
|
||||
|
@ -90,15 +87,15 @@ std::string phonet(const std::string& inword, phonetable& parms) {
|
|||
i = z = 0;
|
||||
while ((c = word[i]) != '\0') {
|
||||
int n = parms.hash[(uchar)c];
|
||||
z0 = 0;
|
||||
int z0 = 0;
|
||||
|
||||
if (n >= 0) {
|
||||
if (n >= 0 && !parms.rules[n].empty()) {
|
||||
/** check all rules for the same letter **/
|
||||
while (parms.rules[n][0] == c) {
|
||||
/** check whole string **/
|
||||
k = 1; /** number of found letters **/
|
||||
p = 5; /** default priority **/
|
||||
s = parms.rules[n];
|
||||
const char*s = parms.rules[n].c_str();
|
||||
s++; /** important for (see below) "*(s-1)" **/
|
||||
|
||||
while (*s != '\0' && word[i + k] == *s && !isdigit((unsigned char)*s) &&
|
||||
|
@ -142,13 +139,13 @@ std::string phonet(const std::string& inword, phonetable& parms) {
|
|||
n0 = parms.hash[(uchar)c0];
|
||||
|
||||
// if (parms.followup && k > 1 && n0 >= 0
|
||||
if (k > 1 && n0 >= 0 && p0 != (int)'-' && word[i + k] != '\0') {
|
||||
if (k > 1 && n0 >= 0 && p0 != (int)'-' && word[i + k] != '\0' && !parms.rules[n0].empty()) {
|
||||
/** test follow-up rule for "word[i+k]" **/
|
||||
while (parms.rules[n0][0] == c0) {
|
||||
/** check whole string **/
|
||||
k0 = k;
|
||||
p0 = 5;
|
||||
s = parms.rules[n0];
|
||||
s = parms.rules[n0].c_str();
|
||||
s++;
|
||||
while (*s != '\0' && word[i + k0] == *s &&
|
||||
!isdigit((unsigned char)*s) &&
|
||||
|
@ -206,9 +203,9 @@ std::string phonet(const std::string& inword, phonetable& parms) {
|
|||
} /** end of follow-up stuff **/
|
||||
|
||||
/** replace string **/
|
||||
s = parms.rules[n + 1];
|
||||
p0 = (parms.rules[n][0] != '\0' &&
|
||||
strchr(parms.rules[n] + 1, '<') != NULL)
|
||||
s = parms.rules[n + 1].c_str();
|
||||
p0 = (!parms.rules[n].empty() &&
|
||||
strchr(parms.rules[n].c_str() + 1, '<') != NULL)
|
||||
? 1
|
||||
: 0;
|
||||
if (p0 == 1 && z == 0) {
|
||||
|
@ -241,8 +238,8 @@ std::string phonet(const std::string& inword, phonetable& parms) {
|
|||
}
|
||||
/** new "actual letter" **/
|
||||
c = *s;
|
||||
if (parms.rules[n][0] != '\0' &&
|
||||
strstr(parms.rules[n] + 1, "^^") != NULL) {
|
||||
if (!parms.rules[n].empty() &&
|
||||
strstr(parms.rules[n].c_str() + 1, "^^") != NULL) {
|
||||
if (c != '\0') {
|
||||
target.push_back(c);
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
Porting from Aspell to Hunspell using C-like structs
|
||||
*/
|
||||
|
||||
#ifndef __PHONETHXX__
|
||||
#define __PHONETHXX__
|
||||
#ifndef PHONET_HXX_
|
||||
#define PHONET_HXX_
|
||||
|
||||
#define HASHSIZE 256
|
||||
#define MAXPHONETLEN 256
|
||||
|
@ -38,9 +38,7 @@
|
|||
|
||||
struct phonetable {
|
||||
char utf8;
|
||||
cs_info* lang;
|
||||
int num;
|
||||
char** rules;
|
||||
std::vector<std::string> rules;
|
||||
int hash[HASHSIZE];
|
||||
};
|
||||
|
||||
|
|
|
@ -90,104 +90,122 @@ RepList::RepList(int n) {
|
|||
|
||||
RepList::~RepList() {
|
||||
for (int i = 0; i < pos; i++) {
|
||||
free(dat[i]->pattern);
|
||||
free(dat[i]->pattern2);
|
||||
free(dat[i]);
|
||||
delete dat[i];
|
||||
}
|
||||
free(dat);
|
||||
}
|
||||
|
||||
int RepList::get_pos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
replentry* RepList::item(int n) {
|
||||
return dat[n];
|
||||
}
|
||||
|
||||
int RepList::near(const char* word) {
|
||||
int RepList::find(const char* word) {
|
||||
int p1 = 0;
|
||||
int p2 = pos;
|
||||
while ((p2 - p1) > 1) {
|
||||
int p2 = pos - 1;
|
||||
while (p1 <= p2) {
|
||||
int m = (p1 + p2) / 2;
|
||||
int c = strcmp(word, dat[m]->pattern);
|
||||
if (c <= 0) {
|
||||
if (c < 0)
|
||||
p2 = m;
|
||||
else
|
||||
p1 = p2 = m;
|
||||
} else
|
||||
p1 = m;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
int RepList::match(const char* word, int n) {
|
||||
if (strncmp(word, dat[n]->pattern, strlen(dat[n]->pattern)) == 0)
|
||||
return strlen(dat[n]->pattern);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RepList::add(char* pat1, char* pat2) {
|
||||
if (pos >= size || pat1 == NULL || pat2 == NULL)
|
||||
return 1;
|
||||
replentry* r = (replentry*)malloc(sizeof(replentry));
|
||||
if (r == NULL)
|
||||
return 1;
|
||||
r->pattern = mystrrep(pat1, "_", " ");
|
||||
r->pattern2 = mystrrep(pat2, "_", " ");
|
||||
r->start = false;
|
||||
r->end = false;
|
||||
dat[pos++] = r;
|
||||
for (int i = pos - 1; i > 0; i--) {
|
||||
r = dat[i];
|
||||
if (strcmp(r->pattern, dat[i - 1]->pattern) < 0) {
|
||||
dat[i] = dat[i - 1];
|
||||
dat[i - 1] = r;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RepList::conv(const char* word, char* dest, size_t destsize) {
|
||||
size_t stl = 0;
|
||||
int change = 0;
|
||||
for (size_t i = 0; i < strlen(word); i++) {
|
||||
int n = near(word + i);
|
||||
int l = match(word + i, n);
|
||||
if (l) {
|
||||
size_t replen = strlen(dat[n]->pattern2);
|
||||
if (stl + replen >= destsize)
|
||||
return -1;
|
||||
strcpy(dest + stl, dat[n]->pattern2);
|
||||
stl += replen;
|
||||
i += l - 1;
|
||||
change = 1;
|
||||
} else {
|
||||
if (stl + 1 >= destsize)
|
||||
return -1;
|
||||
dest[stl++] = word[i];
|
||||
int c = strncmp(word, dat[m]->pattern.c_str(), dat[m]->pattern.size());
|
||||
if (c < 0)
|
||||
p2 = m - 1;
|
||||
else if (c > 0)
|
||||
p1 = m + 1;
|
||||
else { // scan back for a longer match
|
||||
for (p1 = m - 1; p1 >= 0; --p1)
|
||||
if (!strncmp(word, dat[p1]->pattern.c_str(), dat[p1]->pattern.size()))
|
||||
m = p1;
|
||||
else if (dat[p1]->pattern.size() < dat[m]->pattern.size())
|
||||
break;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
dest[stl] = '\0';
|
||||
return change;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool RepList::conv(const char* word, std::string& dest) {
|
||||
std::string RepList::replace(const char* word, int ind, bool atstart) {
|
||||
int type = atstart ? 1 : 0;
|
||||
if (ind < 0)
|
||||
return std::string();
|
||||
if (strlen(word) == dat[ind]->pattern.size())
|
||||
type = atstart ? 3 : 2;
|
||||
while (type && dat[ind]->outstrings[type].empty())
|
||||
type = (type == 2 && !atstart) ? 0 : type - 1;
|
||||
return dat[ind]->outstrings[type];
|
||||
}
|
||||
|
||||
int RepList::add(const std::string& in_pat1, const std::string& pat2) {
|
||||
if (pos >= size || in_pat1.empty() || pat2.empty()) {
|
||||
return 1;
|
||||
}
|
||||
// analyse word context
|
||||
int type = 0;
|
||||
std::string pat1(in_pat1);
|
||||
if (pat1[0] == '_') {
|
||||
pat1.erase(0, 1);
|
||||
type = 1;
|
||||
}
|
||||
if (!pat1.empty() && pat1[pat1.size() - 1] == '_') {
|
||||
type = type + 2;
|
||||
pat1.erase(pat1.size() - 1);
|
||||
}
|
||||
mystrrep(pat1, "_", " ");
|
||||
|
||||
// find existing entry
|
||||
int m = find(pat1.c_str());
|
||||
if (m >= 0 && dat[m]->pattern == pat1) {
|
||||
// since already used
|
||||
dat[m]->outstrings[type] = pat2;
|
||||
mystrrep(dat[m]->outstrings[type], "_", " ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make a new entry if none exists
|
||||
replentry* r = new replentry;
|
||||
if (r == NULL)
|
||||
return 1;
|
||||
r->pattern = pat1;
|
||||
r->outstrings[type] = pat2;
|
||||
mystrrep(r->outstrings[type], "_", " ");
|
||||
dat[pos++] = r;
|
||||
// sort to the right place in the list
|
||||
int i;
|
||||
for (i = pos - 1; i > 0; i--) {
|
||||
int c = strncmp(r->pattern.c_str(), dat[i-1]->pattern.c_str(), dat[i-1]->pattern.size());
|
||||
if (c > 0)
|
||||
break;
|
||||
else if (c == 0) { // subpatterns match. Patterns can't be identical since would catch earlier
|
||||
for (int j = i - 2; j > 0 && !strncmp(dat[i-1]->pattern.c_str(), dat[j]->pattern.c_str(), dat[i-1]->pattern.size()); --j)
|
||||
if (dat[j]->pattern.size() > r->pattern.size() ||
|
||||
(dat[j]->pattern.size() == r->pattern.size() && strncmp(dat[j]->pattern.c_str(), r->pattern.c_str(), r->pattern.size()) > 0)) {
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
memmove(dat + i + 1, dat + i, (pos - i - 1) * sizeof(replentry *));
|
||||
dat[i] = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool RepList::conv(const std::string& in_word, std::string& dest) {
|
||||
dest.clear();
|
||||
|
||||
size_t wordlen = in_word.size();
|
||||
const char* word = in_word.c_str();
|
||||
|
||||
bool change = false;
|
||||
for (size_t i = 0; i < strlen(word); i++) {
|
||||
int n = near(word + i);
|
||||
int l = match(word + i, n);
|
||||
if (l) {
|
||||
dest.append(dat[n]->pattern2);
|
||||
i += l - 1;
|
||||
for (size_t i = 0; i < wordlen; ++i) {
|
||||
int n = find(word + i);
|
||||
std::string l = replace(word + i, n, i == 0);
|
||||
if (!l.empty()) {
|
||||
dest.append(l);
|
||||
i += dat[n]->pattern.size() - 1;
|
||||
change = true;
|
||||
} else {
|
||||
dest.push_back(word[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,17 +72,15 @@
|
|||
*/
|
||||
|
||||
/* string replacement list class */
|
||||
#ifndef _REPLIST_HXX_
|
||||
#define _REPLIST_HXX_
|
||||
|
||||
#include "hunvisapi.h"
|
||||
#ifndef REPLIST_HXX_
|
||||
#define REPLIST_HXX_
|
||||
|
||||
#include "w_char.hxx"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class LIBHUNSPELL_DLL_EXPORTED RepList {
|
||||
class RepList {
|
||||
private:
|
||||
RepList(const RepList&);
|
||||
RepList& operator=(const RepList&);
|
||||
|
@ -93,15 +91,13 @@ class LIBHUNSPELL_DLL_EXPORTED RepList {
|
|||
int pos;
|
||||
|
||||
public:
|
||||
RepList(int n);
|
||||
explicit RepList(int n);
|
||||
~RepList();
|
||||
|
||||
int get_pos();
|
||||
int add(char* pat1, char* pat2);
|
||||
int add(const std::string& pat1, const std::string& pat2);
|
||||
replentry* item(int n);
|
||||
int near(const char* word);
|
||||
int match(const char* word, int n);
|
||||
int conv(const char* word, char* dest, size_t destsize);
|
||||
bool conv(const char* word, std::string& dest);
|
||||
int find(const char* word);
|
||||
std::string replace(const char* word, int n, bool atstart);
|
||||
bool conv(const std::string& word, std::string& dest);
|
||||
};
|
||||
#endif
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -71,8 +71,8 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SUGGESTMGR_HXX_
|
||||
#define _SUGGESTMGR_HXX_
|
||||
#ifndef SUGGESTMGR_HXX_
|
||||
#define SUGGESTMGR_HXX_
|
||||
|
||||
#define MAX_ROOTS 100
|
||||
#define MAX_WORDS 100
|
||||
|
@ -91,8 +91,6 @@
|
|||
#define NGRAM_LOWERING (1 << 2)
|
||||
#define NGRAM_WEIGHTED (1 << 3)
|
||||
|
||||
#include "hunvisapi.h"
|
||||
|
||||
#include "atypes.hxx"
|
||||
#include "affixmgr.hxx"
|
||||
#include "hashmgr.hxx"
|
||||
|
@ -101,22 +99,22 @@
|
|||
|
||||
enum { LCS_UP, LCS_LEFT, LCS_UPLEFT };
|
||||
|
||||
class LIBHUNSPELL_DLL_EXPORTED SuggestMgr {
|
||||
class SuggestMgr {
|
||||
private:
|
||||
SuggestMgr(const SuggestMgr&);
|
||||
SuggestMgr& operator=(const SuggestMgr&);
|
||||
|
||||
private:
|
||||
char* ckey;
|
||||
int ckeyl;
|
||||
w_char* ckey_utf;
|
||||
size_t ckeyl;
|
||||
std::vector<w_char> ckey_utf;
|
||||
|
||||
char* ctry;
|
||||
int ctryl;
|
||||
w_char* ctry_utf;
|
||||
size_t ctryl;
|
||||
std::vector<w_char> ctry_utf;
|
||||
|
||||
AffixMgr* pAMgr;
|
||||
int maxSug;
|
||||
unsigned int maxSug;
|
||||
struct cs_info* csconv;
|
||||
int utf8;
|
||||
int langnum;
|
||||
|
@ -126,62 +124,53 @@ class LIBHUNSPELL_DLL_EXPORTED SuggestMgr {
|
|||
int complexprefixes;
|
||||
|
||||
public:
|
||||
SuggestMgr(const char* tryme, int maxn, AffixMgr* aptr);
|
||||
SuggestMgr(const char* tryme, unsigned int maxn, AffixMgr* aptr);
|
||||
~SuggestMgr();
|
||||
|
||||
int suggest(char*** slst, const char* word, int nsug, int* onlycmpdsug);
|
||||
int ngsuggest(char** wlst, const char* word, int ns, HashMgr** pHMgr, int md);
|
||||
int suggest_auto(char*** slst, const char* word, int nsug);
|
||||
int suggest_stems(char*** slst, const char* word, int nsug);
|
||||
int suggest_pos_stems(char*** slst, const char* word, int nsug);
|
||||
void suggest(std::vector<std::string>& slst, const char* word, int* onlycmpdsug);
|
||||
void ngsuggest(std::vector<std::string>& slst, const char* word, const std::vector<HashMgr*>& rHMgr);
|
||||
|
||||
char* suggest_morph(const char* word);
|
||||
char* suggest_gen(char** pl, int pln, const char* pattern);
|
||||
char* suggest_morph_for_spelling_error(const char* word);
|
||||
std::string suggest_morph(const std::string& word);
|
||||
std::string suggest_gen(const std::vector<std::string>& pl, const std::string& pattern);
|
||||
|
||||
private:
|
||||
int testsug(char** wlst,
|
||||
const char* candidate,
|
||||
int wl,
|
||||
int ns,
|
||||
int cpdsuggest,
|
||||
int* timer,
|
||||
clock_t* timelimit);
|
||||
int checkword(const char*, int, int, int*, clock_t*);
|
||||
void testsug(std::vector<std::string>& wlst,
|
||||
const std::string& candidate,
|
||||
int cpdsuggest,
|
||||
int* timer,
|
||||
clock_t* timelimit);
|
||||
int checkword(const std::string& word, int, int*, clock_t*);
|
||||
int check_forbidden(const char*, int);
|
||||
|
||||
int capchars(char**, const char*, int, int);
|
||||
int replchars(char**, const char*, int, int);
|
||||
int doubletwochars(char**, const char*, int, int);
|
||||
int forgotchar(char**, const char*, int, int);
|
||||
int swapchar(char**, const char*, int, int);
|
||||
int longswapchar(char**, const char*, int, int);
|
||||
int movechar(char**, const char*, int, int);
|
||||
int extrachar(char**, const char*, int, int);
|
||||
int badcharkey(char**, const char*, int, int);
|
||||
int badchar(char**, const char*, int, int);
|
||||
int twowords(char**, const char*, int, int);
|
||||
int fixstems(char**, const char*, int);
|
||||
void capchars(std::vector<std::string>&, const char*, int);
|
||||
int replchars(std::vector<std::string>&, const char*, int);
|
||||
int doubletwochars(std::vector<std::string>&, const char*, int);
|
||||
int forgotchar(std::vector<std::string>&, const char*, int);
|
||||
int swapchar(std::vector<std::string>&, const char*, int);
|
||||
int longswapchar(std::vector<std::string>&, const char*, int);
|
||||
int movechar(std::vector<std::string>&, const char*, int);
|
||||
int extrachar(std::vector<std::string>&, const char*, int);
|
||||
int badcharkey(std::vector<std::string>&, const char*, int);
|
||||
int badchar(std::vector<std::string>&, const char*, int);
|
||||
int twowords(std::vector<std::string>&, const char*, int);
|
||||
|
||||
int capchars_utf(char**, const w_char*, int wl, int, int);
|
||||
int doubletwochars_utf(char**, const w_char*, int wl, int, int);
|
||||
int forgotchar_utf(char**, const w_char*, int wl, int, int);
|
||||
int extrachar_utf(char**, const w_char*, int wl, int, int);
|
||||
int badcharkey_utf(char**, const w_char*, int wl, int, int);
|
||||
int badchar_utf(char**, const w_char*, int wl, int, int);
|
||||
int swapchar_utf(char**, const w_char*, int wl, int, int);
|
||||
int longswapchar_utf(char**, const w_char*, int, int, int);
|
||||
int movechar_utf(char**, const w_char*, int, int, int);
|
||||
void capchars_utf(std::vector<std::string>&, const w_char*, int wl, int);
|
||||
int doubletwochars_utf(std::vector<std::string>&, const w_char*, int wl, int);
|
||||
int forgotchar_utf(std::vector<std::string>&, const w_char*, int wl, int);
|
||||
int extrachar_utf(std::vector<std::string>&, const w_char*, int wl, int);
|
||||
int badcharkey_utf(std::vector<std::string>&, const w_char*, int wl, int);
|
||||
int badchar_utf(std::vector<std::string>&, const w_char*, int wl, int);
|
||||
int swapchar_utf(std::vector<std::string>&, const w_char*, int wl, int);
|
||||
int longswapchar_utf(std::vector<std::string>&, const w_char*, int, int);
|
||||
int movechar_utf(std::vector<std::string>&, const w_char*, int, int);
|
||||
|
||||
int mapchars(char**, const char*, int, int);
|
||||
int mapchars(std::vector<std::string>&, const char*, int);
|
||||
int map_related(const char*,
|
||||
std::string&,
|
||||
int,
|
||||
char** wlst,
|
||||
int,
|
||||
int,
|
||||
const mapentry*,
|
||||
std::vector<std::string>& wlst,
|
||||
int,
|
||||
const std::vector<mapentry>&,
|
||||
int*,
|
||||
clock_t*);
|
||||
int ngram(int n, const std::string& s1, const std::string& s2, int opt);
|
||||
|
@ -192,7 +181,7 @@ class LIBHUNSPELL_DLL_EXPORTED SuggestMgr {
|
|||
void lcs(const char* s, const char* s2, int* l1, int* l2, char** result);
|
||||
int lcslen(const char* s, const char* s2);
|
||||
int lcslen(const std::string& s, const std::string& s2);
|
||||
char* suggest_hentry_gen(hentry* rv, const char* pattern);
|
||||
std::string suggest_hentry_gen(hentry* rv, const char* pattern);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,8 +38,10 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __WCHARHXX__
|
||||
#define __WCHARHXX__
|
||||
#ifndef W_CHAR_HXX_
|
||||
#define W_CHAR_HXX_
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef GCC
|
||||
struct w_char {
|
||||
|
@ -66,10 +68,8 @@ struct __attribute__((packed)) w_char {
|
|||
|
||||
// two character arrays
|
||||
struct replentry {
|
||||
char* pattern;
|
||||
char* pattern2;
|
||||
bool start;
|
||||
bool end;
|
||||
std::string pattern;
|
||||
std::string outstrings[4]; // med, ini, fin, isol
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'mozEnglishWordUtils.cpp',
|
||||
'mozInlineSpellChecker.cpp',
|
||||
'mozInlineSpellWordUtil.cpp',
|
||||
|
|
|
@ -1608,6 +1608,11 @@ js::RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto, uint8_t* resul
|
|||
if (!GetGetterPure(cx, proto, NameToId(cx->names().flags), &flagsGetter))
|
||||
return false;
|
||||
|
||||
if (!flagsGetter) {
|
||||
*result = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsSelfHostedFunctionWithName(flagsGetter, cx->names().RegExpFlagsGetter)) {
|
||||
*result = false;
|
||||
return true;
|
||||
|
|
|
@ -100,4 +100,30 @@
|
|||
#define MODULE_STATE_INSTANTIATED 2
|
||||
#define MODULE_STATE_EVALUATED 3
|
||||
|
||||
#define STRING_GENERICS_CHAR_AT 0
|
||||
#define STRING_GENERICS_CHAR_CODE_AT 1
|
||||
#define STRING_GENERICS_CONCAT 2
|
||||
#define STRING_GENERICS_ENDS_WITH 3
|
||||
#define STRING_GENERICS_INCLUDES 4
|
||||
#define STRING_GENERICS_INDEX_OF 5
|
||||
#define STRING_GENERICS_LAST_INDEX_OF 6
|
||||
#define STRING_GENERICS_LOCALE_COMPARE 7
|
||||
#define STRING_GENERICS_MATCH 8
|
||||
#define STRING_GENERICS_NORMALIZE 9
|
||||
#define STRING_GENERICS_REPLACE 10
|
||||
#define STRING_GENERICS_SEARCH 11
|
||||
#define STRING_GENERICS_SLICE 12
|
||||
#define STRING_GENERICS_SPLIT 13
|
||||
#define STRING_GENERICS_STARTS_WITH 14
|
||||
#define STRING_GENERICS_SUBSTR 15
|
||||
#define STRING_GENERICS_SUBSTRING 16
|
||||
#define STRING_GENERICS_TO_LOWER_CASE 17
|
||||
#define STRING_GENERICS_TO_LOCALE_LOWER_CASE 18
|
||||
#define STRING_GENERICS_TO_LOCALE_UPPER_CASE 19
|
||||
#define STRING_GENERICS_TO_UPPER_CASE 20
|
||||
#define STRING_GENERICS_TRIM 21
|
||||
#define STRING_GENERICS_TRIM_LEFT 22
|
||||
#define STRING_GENERICS_TRIM_RIGHT 23
|
||||
#define STRING_GENERICS_METHODS_LIMIT 24
|
||||
|
||||
#endif
|
||||
|
|
|
@ -58,6 +58,7 @@ function String_match(regexp) {
|
|||
}
|
||||
|
||||
function String_generic_match(thisValue, regexp) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_MATCH, 'match');
|
||||
if (thisValue === undefined)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.match');
|
||||
return callFunction(String_match, thisValue, regexp);
|
||||
|
@ -192,6 +193,7 @@ function String_replace(searchValue, replaceValue) {
|
|||
}
|
||||
|
||||
function String_generic_replace(thisValue, searchValue, replaceValue) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_REPLACE, 'replace');
|
||||
if (thisValue === undefined)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.replace');
|
||||
return callFunction(String_replace, thisValue, searchValue, replaceValue);
|
||||
|
@ -247,6 +249,7 @@ function String_search(regexp) {
|
|||
}
|
||||
|
||||
function String_generic_search(thisValue, regexp) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_SEARCH, 'search');
|
||||
if (thisValue === undefined)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.search');
|
||||
return callFunction(String_search, thisValue, regexp);
|
||||
|
@ -328,6 +331,7 @@ function String_split(separator, limit) {
|
|||
}
|
||||
|
||||
function String_generic_split(thisValue, separator, limit) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_SPLIT, 'split');
|
||||
if (thisValue === undefined)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.split');
|
||||
return callFunction(String_split, thisValue, separator, limit);
|
||||
|
@ -372,6 +376,7 @@ function String_substring(start, end) {
|
|||
}
|
||||
|
||||
function String_static_substring(string, start, end) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_SUBSTRING, 'substring');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.substring');
|
||||
return callFunction(String_substring, string, start, end);
|
||||
|
@ -411,6 +416,7 @@ function String_substr(start, length) {
|
|||
}
|
||||
|
||||
function String_static_substr(string, start, length) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_SUBSTR, 'substr');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.substr');
|
||||
return callFunction(String_substr, string, start, length);
|
||||
|
@ -448,6 +454,7 @@ function String_slice(start, end) {
|
|||
}
|
||||
|
||||
function String_static_slice(string, start, end) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_SLICE, 'slice');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.slice');
|
||||
return callFunction(String_slice, string, start, end);
|
||||
|
@ -655,6 +662,7 @@ function String_static_raw(callSite, ...substitutions) {
|
|||
* Spec: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String#String_generic_methods
|
||||
*/
|
||||
function String_static_localeCompare(str1, str2) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_LOCALE_COMPARE, 'localeCompare');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "String.localeCompare");
|
||||
var locales = arguments.length > 2 ? arguments[2] : undefined;
|
||||
|
@ -767,30 +775,35 @@ function String_link(url) {
|
|||
}
|
||||
|
||||
function String_static_toLowerCase(string) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_TO_LOWER_CASE, 'toLowerCase');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toLowerCase');
|
||||
return callFunction(std_String_toLowerCase, string);
|
||||
}
|
||||
|
||||
function String_static_toUpperCase(string) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_TO_UPPER_CASE, 'toUpperCase');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toUpperCase');
|
||||
return callFunction(std_String_toUpperCase, string);
|
||||
}
|
||||
|
||||
function String_static_charAt(string, pos) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_CHAR_AT, 'charAt');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.charAt');
|
||||
return callFunction(std_String_charAt, string, pos);
|
||||
}
|
||||
|
||||
function String_static_charCodeAt(string, pos) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_CHAR_CODE_AT, 'charCodeAt');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.charCodeAt');
|
||||
return callFunction(std_String_charCodeAt, string, pos);
|
||||
}
|
||||
|
||||
function String_static_includes(string, searchString) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_INCLUDES, 'includes');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.includes');
|
||||
var position = arguments.length > 2 ? arguments[2] : undefined;
|
||||
|
@ -798,6 +811,7 @@ function String_static_includes(string, searchString) {
|
|||
}
|
||||
|
||||
function String_static_indexOf(string, searchString) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_INDEX_OF, 'indexOf');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.indexOf');
|
||||
var position = arguments.length > 2 ? arguments[2] : undefined;
|
||||
|
@ -805,6 +819,7 @@ function String_static_indexOf(string, searchString) {
|
|||
}
|
||||
|
||||
function String_static_lastIndexOf(string, searchString) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_LAST_INDEX_OF, 'lastIndexOf');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.lastIndexOf');
|
||||
var position = arguments.length > 2 ? arguments[2] : undefined;
|
||||
|
@ -812,6 +827,7 @@ function String_static_lastIndexOf(string, searchString) {
|
|||
}
|
||||
|
||||
function String_static_startsWith(string, searchString) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_STARTS_WITH, 'startsWith');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.startsWith');
|
||||
var position = arguments.length > 2 ? arguments[2] : undefined;
|
||||
|
@ -819,6 +835,7 @@ function String_static_startsWith(string, searchString) {
|
|||
}
|
||||
|
||||
function String_static_endsWith(string, searchString) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_ENDS_WITH, 'endsWith');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.endsWith');
|
||||
var endPosition = arguments.length > 2 ? arguments[2] : undefined;
|
||||
|
@ -826,30 +843,35 @@ function String_static_endsWith(string, searchString) {
|
|||
}
|
||||
|
||||
function String_static_trim(string) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_TRIM, 'trim');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trim');
|
||||
return callFunction(std_String_trim, string);
|
||||
}
|
||||
|
||||
function String_static_trimLeft(string) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_TRIM_LEFT, 'trimLeft');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimLeft');
|
||||
return callFunction(std_String_trimLeft, string);
|
||||
}
|
||||
|
||||
function String_static_trimRight(string) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_TRIM_RIGHT, 'trimRight');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimRight');
|
||||
return callFunction(std_String_trimRight, string);
|
||||
}
|
||||
|
||||
function String_static_toLocaleLowerCase(string) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_TO_LOCALE_LOWER_CASE, 'toLocaleLowerCase');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toLocaleLowerCase');
|
||||
return callFunction(std_String_toLocaleLowerCase, string);
|
||||
}
|
||||
|
||||
function String_static_toLocaleUpperCase(string) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_TO_LOCALE_UPPER_CASE, 'toLocaleUpperCase');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toLocaleUpperCase');
|
||||
return callFunction(std_String_toLocaleUpperCase, string);
|
||||
|
@ -857,6 +879,7 @@ function String_static_toLocaleUpperCase(string) {
|
|||
|
||||
#if EXPOSE_INTL_API
|
||||
function String_static_normalize(string) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_NORMALIZE, "normalize");
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.normalize');
|
||||
var form = arguments.length > 1 ? arguments[1] : undefined;
|
||||
|
@ -865,6 +888,7 @@ function String_static_normalize(string) {
|
|||
#endif
|
||||
|
||||
function String_static_concat(string, arg1) {
|
||||
WarnDeprecatedStringMethod(STRING_GENERICS_CONCAT, 'concat');
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.concat');
|
||||
var args = callFunction(std_Array_slice, arguments, 1);
|
||||
|
|
|
@ -944,6 +944,17 @@ BaselineCacheIRCompiler::emitGuardIsSymbol()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitGuardIsInt32()
|
||||
{
|
||||
ValueOperand input = allocator.useValueRegister(masm, reader.valOperandId());
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
masm.branchTestInt32(Assembler::NotEqual, input, failure->label());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitGuardType()
|
||||
{
|
||||
|
@ -1561,13 +1572,101 @@ bool
|
|||
BaselineCacheIRCompiler::emitLoadStringLengthResult()
|
||||
{
|
||||
Register str = allocator.useRegister(masm, reader.stringOperandId());
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
|
||||
masm.loadStringLength(str, R0.scratchReg());
|
||||
masm.tagValue(JSVAL_TYPE_INT32, R0.scratchReg(), R0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitLoadStringCharResult()
|
||||
{
|
||||
Register str = allocator.useRegister(masm, reader.stringOperandId());
|
||||
Register index = allocator.useRegister(masm, reader.int32OperandId());
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.branchIfRope(str, failure->label());
|
||||
|
||||
// Bounds check, load string char.
|
||||
masm.branch32(Assembler::BelowOrEqual, Address(str, JSString::offsetOfLength()),
|
||||
index, failure->label());
|
||||
masm.loadStringChar(str, index, scratch);
|
||||
|
||||
// Load StaticString for this char.
|
||||
masm.branch32(Assembler::AboveOrEqual, scratch, Imm32(StaticStrings::UNIT_STATIC_LIMIT),
|
||||
failure->label());
|
||||
masm.movePtr(ImmPtr(&cx_->staticStrings().unitStaticTable), R0.scratchReg());
|
||||
masm.loadPtr(BaseIndex(R0.scratchReg(), scratch, ScalePointer), R0.scratchReg());
|
||||
|
||||
masm.tagValue(JSVAL_TYPE_STRING, R0.scratchReg(), R0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitLoadFrameArgumentResult()
|
||||
{
|
||||
Register index = allocator.useRegister(masm, reader.int32OperandId());
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
// Bounds check.
|
||||
masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::offsetOfNumActualArgs()), scratch);
|
||||
masm.branch32(Assembler::AboveOrEqual, index, scratch, failure->label());
|
||||
|
||||
// Load the argument.
|
||||
masm.loadValue(BaseValueIndex(BaselineFrameReg, index, BaselineFrame::offsetOfArg(0)), R0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitLoadArgumentsObjectArgResult()
|
||||
{
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
Register index = allocator.useRegister(masm, reader.int32OperandId());
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
// Get initial length value.
|
||||
masm.unboxInt32(Address(obj, ArgumentsObject::getInitialLengthSlotOffset()), scratch);
|
||||
|
||||
// Ensure no overridden length/element.
|
||||
masm.branchTest32(Assembler::NonZero,
|
||||
scratch,
|
||||
Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT |
|
||||
ArgumentsObject::ELEMENT_OVERRIDDEN_BIT),
|
||||
failure->label());
|
||||
|
||||
// Bounds check.
|
||||
masm.rshift32(Imm32(ArgumentsObject::PACKED_BITS_COUNT), scratch);
|
||||
masm.branch32(Assembler::AboveOrEqual, index, scratch, failure->label());
|
||||
|
||||
// Load ArgumentsData.
|
||||
masm.loadPrivate(Address(obj, ArgumentsObject::getDataSlotOffset()), scratch);
|
||||
|
||||
// Fail if we have a RareArgumentsData (elements were deleted).
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(scratch, offsetof(ArgumentsData, rareData)),
|
||||
ImmWord(0),
|
||||
failure->label());
|
||||
|
||||
// Guard the argument is not a FORWARD_TO_CALL_SLOT MagicValue. Note that
|
||||
// the order here matters: we should only clobber R0 after emitting the last
|
||||
// guard.
|
||||
BaseValueIndex argValue(scratch, index, ArgumentsData::offsetOfArgs());
|
||||
masm.branchTestMagic(Assembler::Equal, argValue, failure->label());
|
||||
masm.loadValue(argValue, R0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitTypeMonitorResult()
|
||||
{
|
||||
|
|
|
@ -865,18 +865,6 @@ TypedArrayGetElemStubExists(ICGetElem_Fallback* stub, HandleObject obj)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
ArgumentsGetElemStubExists(ICGetElem_Fallback* stub, ICGetElem_Arguments::Which which)
|
||||
{
|
||||
for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
|
||||
if (!iter->isGetElem_Arguments())
|
||||
continue;
|
||||
if (iter->toGetElem_Arguments()->which() == which)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsOptimizableElementPropertyName(JSContext* cx, HandleValue key, MutableHandleId idp)
|
||||
{
|
||||
|
@ -951,64 +939,10 @@ static bool
|
|||
TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_Fallback* stub,
|
||||
HandleValue lhs, HandleValue rhs, HandleValue res, bool* attached)
|
||||
{
|
||||
// Check for String[i] => Char accesses.
|
||||
if (lhs.isString() && rhs.isInt32() && res.isString() &&
|
||||
!stub->hasStub(ICStub::GetElem_String))
|
||||
{
|
||||
// NoSuchMethod handling doesn't apply to string targets.
|
||||
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetElem(String[Int32]) stub");
|
||||
ICGetElem_String::Compiler compiler(cx);
|
||||
ICStub* stringStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!stringStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(stringStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lhs.isMagic(JS_OPTIMIZED_ARGUMENTS) && rhs.isInt32() &&
|
||||
!ArgumentsGetElemStubExists(stub, ICGetElem_Arguments::Magic))
|
||||
{
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetElem(MagicArgs[Int32]) stub");
|
||||
ICGetElem_Arguments::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
|
||||
ICGetElem_Arguments::Magic);
|
||||
ICStub* argsStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!argsStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(argsStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, GetElem is only optimized on objects.
|
||||
if (!lhs.isObject())
|
||||
return true;
|
||||
RootedObject obj(cx, &lhs.toObject());
|
||||
|
||||
// Check for ArgumentsObj[int] accesses
|
||||
if (obj->is<ArgumentsObject>() && rhs.isInt32() &&
|
||||
!obj->as<ArgumentsObject>().hasOverriddenElement())
|
||||
{
|
||||
ICGetElem_Arguments::Which which = ICGetElem_Arguments::Mapped;
|
||||
if (obj->is<UnmappedArgumentsObject>())
|
||||
which = ICGetElem_Arguments::Unmapped;
|
||||
if (!ArgumentsGetElemStubExists(stub, which)) {
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetElem(ArgsObj[Int32]) stub");
|
||||
ICGetElem_Arguments::Compiler compiler(
|
||||
cx, stub->fallbackMonitorStub()->firstMonitorStub(), which);
|
||||
ICStub* argsStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!argsStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(argsStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for NativeObject[int] dense accesses.
|
||||
if (IsNativeDenseElementAccess(obj, rhs)) {
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetElem(Native[Int32] dense) stub");
|
||||
|
@ -1192,56 +1126,6 @@ ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
|
|||
return tailCallVM(DoGetElemFallbackInfo, masm);
|
||||
}
|
||||
|
||||
//
|
||||
// GetElem_String
|
||||
//
|
||||
|
||||
bool
|
||||
ICGetElem_String::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
MOZ_ASSERT(engine_ == Engine::Baseline);
|
||||
|
||||
Label failure;
|
||||
masm.branchTestString(Assembler::NotEqual, R0, &failure);
|
||||
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
|
||||
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
|
||||
Register scratchReg = regs.takeAny();
|
||||
|
||||
// Unbox string in R0.
|
||||
Register str = masm.extractString(R0, ExtractTemp0);
|
||||
|
||||
// Check for non-linear strings.
|
||||
masm.branchIfRope(str, &failure);
|
||||
|
||||
// Unbox key.
|
||||
Register key = masm.extractInt32(R1, ExtractTemp1);
|
||||
|
||||
// Bounds check.
|
||||
masm.branch32(Assembler::BelowOrEqual, Address(str, JSString::offsetOfLength()),
|
||||
key, &failure);
|
||||
|
||||
// Get char code.
|
||||
masm.loadStringChar(str, key, scratchReg);
|
||||
|
||||
// Check if char code >= UNIT_STATIC_LIMIT.
|
||||
masm.branch32(Assembler::AboveOrEqual, scratchReg, Imm32(StaticStrings::UNIT_STATIC_LIMIT),
|
||||
&failure);
|
||||
|
||||
// Load static string.
|
||||
masm.movePtr(ImmPtr(&cx->staticStrings().unitStaticTable), str);
|
||||
masm.loadPtr(BaseIndex(str, scratchReg, ScalePointer), str);
|
||||
|
||||
// Return.
|
||||
masm.tagValue(JSVAL_TYPE_STRING, str, R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// GetElem_Dense
|
||||
//
|
||||
|
@ -1422,131 +1306,6 @@ ICGetElem_TypedArray::Compiler::generateStubCode(MacroAssembler& masm)
|
|||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// GetElem_Arguments
|
||||
//
|
||||
bool
|
||||
ICGetElem_Arguments::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
MOZ_ASSERT(engine_ == Engine::Baseline);
|
||||
|
||||
Label failure;
|
||||
if (which_ == ICGetElem_Arguments::Magic) {
|
||||
// Ensure that this is a magic arguments value.
|
||||
masm.branchTestMagicValue(Assembler::NotEqual, R0, JS_OPTIMIZED_ARGUMENTS, &failure);
|
||||
|
||||
// Ensure that frame has not loaded different arguments object since.
|
||||
masm.branchTest32(Assembler::NonZero,
|
||||
Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags()),
|
||||
Imm32(BaselineFrame::HAS_ARGS_OBJ),
|
||||
&failure);
|
||||
|
||||
// Ensure that index is an integer.
|
||||
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
|
||||
Register idx = masm.extractInt32(R1, ExtractTemp1);
|
||||
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
|
||||
Register scratch = regs.takeAny();
|
||||
|
||||
// Load num actual arguments
|
||||
Address actualArgs(BaselineFrameReg, BaselineFrame::offsetOfNumActualArgs());
|
||||
masm.loadPtr(actualArgs, scratch);
|
||||
|
||||
// Ensure idx < argc
|
||||
masm.branch32(Assembler::AboveOrEqual, idx, scratch, &failure);
|
||||
|
||||
// Load argval
|
||||
masm.movePtr(BaselineFrameReg, scratch);
|
||||
masm.addPtr(Imm32(BaselineFrame::offsetOfArg(0)), scratch);
|
||||
BaseValueIndex element(scratch, idx);
|
||||
masm.loadValue(element, R0);
|
||||
|
||||
// Enter type monitor IC to type-check result.
|
||||
EmitEnterTypeMonitorIC(masm);
|
||||
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(which_ == ICGetElem_Arguments::Mapped ||
|
||||
which_ == ICGetElem_Arguments::Unmapped);
|
||||
|
||||
const Class* clasp = (which_ == ICGetElem_Arguments::Mapped)
|
||||
? &MappedArgumentsObject::class_
|
||||
: &UnmappedArgumentsObject::class_;
|
||||
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
|
||||
Register scratchReg = regs.takeAny();
|
||||
|
||||
// Guard on input being an arguments object.
|
||||
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||
masm.branchTestObjClass(Assembler::NotEqual, objReg, scratchReg, clasp, &failure);
|
||||
|
||||
// Guard on index being int32
|
||||
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
|
||||
Register idxReg = masm.extractInt32(R1, ExtractTemp1);
|
||||
|
||||
// Get initial ArgsObj length value.
|
||||
masm.unboxInt32(Address(objReg, ArgumentsObject::getInitialLengthSlotOffset()), scratchReg);
|
||||
|
||||
// Test if length or any element have been overridden.
|
||||
masm.branchTest32(Assembler::NonZero,
|
||||
scratchReg,
|
||||
Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT |
|
||||
ArgumentsObject::ELEMENT_OVERRIDDEN_BIT),
|
||||
&failure);
|
||||
|
||||
// Length has not been overridden, ensure that R1 is an integer and is <= length.
|
||||
masm.rshiftPtr(Imm32(ArgumentsObject::PACKED_BITS_COUNT), scratchReg);
|
||||
masm.branch32(Assembler::AboveOrEqual, idxReg, scratchReg, &failure);
|
||||
|
||||
// Length check succeeded, now check the correct bit. We clobber potential type regs
|
||||
// now. Inputs will have to be reconstructed if we fail after this point, but that's
|
||||
// unlikely.
|
||||
Label failureReconstructInputs;
|
||||
regs = availableGeneralRegs(0);
|
||||
regs.takeUnchecked(objReg);
|
||||
regs.takeUnchecked(idxReg);
|
||||
regs.take(scratchReg);
|
||||
Register argData = regs.takeAny();
|
||||
|
||||
// Load ArgumentsData
|
||||
masm.loadPrivate(Address(objReg, ArgumentsObject::getDataSlotOffset()), argData);
|
||||
|
||||
// Fail if we have a RareArgumentsData (elements were deleted).
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(argData, offsetof(ArgumentsData, rareData)),
|
||||
ImmWord(0),
|
||||
&failureReconstructInputs);
|
||||
|
||||
// Load the value. Use scratchReg to form a ValueOperand to load into.
|
||||
masm.addPtr(Imm32(ArgumentsData::offsetOfArgs()), argData);
|
||||
regs.add(scratchReg);
|
||||
ValueOperand tempVal = regs.takeAnyValue();
|
||||
masm.loadValue(BaseValueIndex(argData, idxReg), tempVal);
|
||||
|
||||
// Makesure that this is not a FORWARD_TO_CALL_SLOT magic value.
|
||||
masm.branchTestMagic(Assembler::Equal, tempVal, &failureReconstructInputs);
|
||||
|
||||
// Copy value from temp to R0.
|
||||
masm.moveValue(tempVal, R0);
|
||||
|
||||
// Type-check result
|
||||
EmitEnterTypeMonitorIC(masm);
|
||||
|
||||
// Failed, but inputs are deconstructed into object and int, and need to be
|
||||
// reconstructed into values.
|
||||
masm.bind(&failureReconstructInputs);
|
||||
masm.tagValue(JSVAL_TYPE_OBJECT, objReg, R0);
|
||||
masm.tagValue(JSVAL_TYPE_INT32, idxReg, R1);
|
||||
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// SetElem_Fallback
|
||||
//
|
||||
|
@ -7420,13 +7179,6 @@ ICGetElem_TypedArray::ICGetElem_TypedArray(JitCode* stubCode, Shape* shape, Scal
|
|||
MOZ_ASSERT(extra_ == type);
|
||||
}
|
||||
|
||||
/* static */ ICGetElem_Arguments*
|
||||
ICGetElem_Arguments::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
|
||||
ICGetElem_Arguments& other)
|
||||
{
|
||||
return New<ICGetElem_Arguments>(cx, space, other.jitCode(), firstMonitorStub, other.which());
|
||||
}
|
||||
|
||||
ICSetElem_DenseOrUnboxedArray::ICSetElem_DenseOrUnboxedArray(JitCode* stubCode, Shape* shape, ObjectGroup* group)
|
||||
: ICUpdatedStub(SetElem_DenseOrUnboxedArray, stubCode),
|
||||
shape_(shape),
|
||||
|
|
|
@ -419,29 +419,6 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub
|
|||
};
|
||||
};
|
||||
|
||||
class ICGetElem_String : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICGetElem_String(JitCode* stubCode)
|
||||
: ICStub(ICStub::GetElem_String, stubCode) {}
|
||||
|
||||
public:
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::GetElem_String, Engine::Baseline) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) {
|
||||
return newStub<ICGetElem_String>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ICGetElem_Dense : public ICMonitoredStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
@ -583,53 +560,6 @@ class ICGetElem_TypedArray : public ICStub
|
|||
};
|
||||
};
|
||||
|
||||
class ICGetElem_Arguments : public ICMonitoredStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
public:
|
||||
enum Which { Mapped, Unmapped, Magic };
|
||||
|
||||
private:
|
||||
ICGetElem_Arguments(JitCode* stubCode, ICStub* firstMonitorStub, Which which)
|
||||
: ICMonitoredStub(ICStub::GetElem_Arguments, stubCode, firstMonitorStub)
|
||||
{
|
||||
extra_ = static_cast<uint16_t>(which);
|
||||
}
|
||||
|
||||
public:
|
||||
static ICGetElem_Arguments* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
|
||||
ICGetElem_Arguments& other);
|
||||
|
||||
Which which() const {
|
||||
return static_cast<Which>(extra_);
|
||||
}
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
ICStub* firstMonitorStub_;
|
||||
Which which_;
|
||||
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
|
||||
|
||||
virtual int32_t getKey() const {
|
||||
return static_cast<int32_t>(engine_) |
|
||||
(static_cast<int32_t>(kind) << 1) |
|
||||
(static_cast<int32_t>(which_) << 17);
|
||||
}
|
||||
|
||||
public:
|
||||
Compiler(JSContext* cx, ICStub* firstMonitorStub, Which which)
|
||||
: ICStubCompiler(cx, ICStub::GetElem_Arguments, Engine::Baseline),
|
||||
firstMonitorStub_(firstMonitorStub),
|
||||
which_(which)
|
||||
{}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) {
|
||||
return newStub<ICGetElem_Arguments>(space, getStubCode(), firstMonitorStub_, which_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// SetElem
|
||||
// JSOP_SETELEM
|
||||
// JSOP_INITELEM
|
||||
|
|
|
@ -49,11 +49,9 @@ namespace jit {
|
|||
_(Call_IsSuspendedStarGenerator) \
|
||||
\
|
||||
_(GetElem_Fallback) \
|
||||
_(GetElem_String) \
|
||||
_(GetElem_Dense) \
|
||||
_(GetElem_UnboxedArray) \
|
||||
_(GetElem_TypedArray) \
|
||||
_(GetElem_Arguments) \
|
||||
\
|
||||
_(SetElem_Fallback) \
|
||||
_(SetElem_DenseOrUnboxedArray) \
|
||||
|
|
|
@ -1016,11 +1016,6 @@ BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc)
|
|||
case ICStub::GetProp_Generic:
|
||||
return MIRType::Value;
|
||||
|
||||
case ICStub::GetElem_Arguments:
|
||||
// Either an object or magic arguments.
|
||||
return MIRType::Value;
|
||||
|
||||
case ICStub::GetElem_String:
|
||||
case ICStub::GetElem_Dense:
|
||||
case ICStub::GetElem_TypedArray:
|
||||
case ICStub::GetElem_UnboxedArray:
|
||||
|
|
|
@ -85,6 +85,13 @@ GetPropIRGenerator::tryAttachStub()
|
|||
return true;
|
||||
if (tryAttachProxy(obj, objId, id))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (idVal_.isInt32()) {
|
||||
ValOperandId indexId = getElemKeyValueId();
|
||||
if (tryAttachArgumentsObjectArg(obj, objId, indexId))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -94,8 +101,18 @@ GetPropIRGenerator::tryAttachStub()
|
|||
return true;
|
||||
if (tryAttachStringLength(valId, id))
|
||||
return true;
|
||||
if (tryAttachMagicArguments(valId, id))
|
||||
if (tryAttachMagicArgumentsName(valId, id))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (idVal_.isInt32()) {
|
||||
ValOperandId indexId = getElemKeyValueId();
|
||||
if (tryAttachStringChar(valId, indexId))
|
||||
return true;
|
||||
if (tryAttachMagicArgument(valId, indexId))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -775,7 +792,31 @@ GetPropIRGenerator::tryAttachStringLength(ValOperandId valId, HandleId id)
|
|||
}
|
||||
|
||||
bool
|
||||
GetPropIRGenerator::tryAttachMagicArguments(ValOperandId valId, HandleId id)
|
||||
GetPropIRGenerator::tryAttachStringChar(ValOperandId valId, ValOperandId indexId)
|
||||
{
|
||||
MOZ_ASSERT(idVal_.isInt32());
|
||||
|
||||
if (!val_.isString())
|
||||
return false;
|
||||
|
||||
JSString* str = val_.toString();
|
||||
int32_t index = idVal_.toInt32();
|
||||
if (size_t(index) >= str->length() ||
|
||||
!str->isLinear() ||
|
||||
str->asLinear().latin1OrTwoByteChar(index) >= StaticStrings::UNIT_STATIC_LIMIT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
StringOperandId strId = writer.guardIsString(valId);
|
||||
Int32OperandId int32IndexId = writer.guardIsInt32(indexId);
|
||||
writer.loadStringCharResult(strId, int32IndexId);
|
||||
writer.returnFromIC();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GetPropIRGenerator::tryAttachMagicArgumentsName(ValOperandId valId, HandleId id)
|
||||
{
|
||||
if (!val_.isMagic(JS_OPTIMIZED_ARGUMENTS))
|
||||
return false;
|
||||
|
@ -799,6 +840,45 @@ GetPropIRGenerator::tryAttachMagicArguments(ValOperandId valId, HandleId id)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GetPropIRGenerator::tryAttachMagicArgument(ValOperandId valId, ValOperandId indexId)
|
||||
{
|
||||
MOZ_ASSERT(idVal_.isInt32());
|
||||
|
||||
if (!val_.isMagic(JS_OPTIMIZED_ARGUMENTS))
|
||||
return false;
|
||||
|
||||
writer.guardMagicValue(valId, JS_OPTIMIZED_ARGUMENTS);
|
||||
writer.guardFrameHasNoArgumentsObject();
|
||||
|
||||
Int32OperandId int32IndexId = writer.guardIsInt32(indexId);
|
||||
writer.loadFrameArgumentResult(int32IndexId);
|
||||
writer.typeMonitorResult();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GetPropIRGenerator::tryAttachArgumentsObjectArg(HandleObject obj, ObjOperandId objId,
|
||||
ValOperandId indexId)
|
||||
{
|
||||
MOZ_ASSERT(idVal_.isInt32());
|
||||
|
||||
if (!obj->is<ArgumentsObject>() || obj->as<ArgumentsObject>().hasOverriddenElement())
|
||||
return false;
|
||||
|
||||
if (obj->is<MappedArgumentsObject>()) {
|
||||
writer.guardClass(objId, GuardClassKind::MappedArguments);
|
||||
} else {
|
||||
MOZ_ASSERT(obj->is<UnmappedArgumentsObject>());
|
||||
writer.guardClass(objId, GuardClassKind::UnmappedArguments);
|
||||
}
|
||||
|
||||
Int32OperandId int32IndexId = writer.guardIsInt32(indexId);
|
||||
writer.loadArgumentsObjectArgResult(objId, int32IndexId);
|
||||
writer.typeMonitorResult();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GetPropIRGenerator::maybeEmitIdGuard(jsid id)
|
||||
{
|
||||
|
|
|
@ -93,6 +93,13 @@ class SymbolOperandId : public OperandId
|
|||
explicit SymbolOperandId(uint16_t id) : OperandId(id) {}
|
||||
};
|
||||
|
||||
class Int32OperandId : public OperandId
|
||||
{
|
||||
public:
|
||||
Int32OperandId() = default;
|
||||
explicit Int32OperandId(uint16_t id) : OperandId(id) {}
|
||||
};
|
||||
|
||||
class TypedOperandId : public OperandId
|
||||
{
|
||||
JSValueType type_;
|
||||
|
@ -107,6 +114,9 @@ class TypedOperandId : public OperandId
|
|||
MOZ_IMPLICIT TypedOperandId(SymbolOperandId id)
|
||||
: OperandId(id.id()), type_(JSVAL_TYPE_SYMBOL)
|
||||
{}
|
||||
MOZ_IMPLICIT TypedOperandId(Int32OperandId id)
|
||||
: OperandId(id.id()), type_(JSVAL_TYPE_INT32)
|
||||
{}
|
||||
|
||||
JSValueType type() const { return type_; }
|
||||
};
|
||||
|
@ -121,6 +131,7 @@ enum class CacheKind : uint8_t
|
|||
_(GuardIsObject) \
|
||||
_(GuardIsString) \
|
||||
_(GuardIsSymbol) \
|
||||
_(GuardIsInt32) \
|
||||
_(GuardType) \
|
||||
_(GuardShape) \
|
||||
_(GuardGroup) \
|
||||
|
@ -150,10 +161,13 @@ enum class CacheKind : uint8_t
|
|||
_(LoadTypedObjectResult) \
|
||||
_(LoadInt32ArrayLengthResult) \
|
||||
_(LoadUnboxedArrayLengthResult) \
|
||||
_(LoadArgumentsObjectArgResult) \
|
||||
_(LoadArgumentsObjectLengthResult) \
|
||||
_(LoadStringCharResult) \
|
||||
_(LoadStringLengthResult) \
|
||||
_(LoadFrameCalleeResult) \
|
||||
_(LoadFrameNumActualArgsResult) \
|
||||
_(LoadFrameArgumentResult) \
|
||||
_(CallScriptedGetterResult) \
|
||||
_(CallNativeGetterResult) \
|
||||
_(CallProxyGetResult) \
|
||||
|
@ -368,6 +382,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
writeOpWithOperandId(CacheOp::GuardIsSymbol, val);
|
||||
return SymbolOperandId(val.id());
|
||||
}
|
||||
Int32OperandId guardIsInt32(ValOperandId val) {
|
||||
writeOpWithOperandId(CacheOp::GuardIsInt32, val);
|
||||
return Int32OperandId(val.id());
|
||||
}
|
||||
void guardType(ValOperandId val, JSValueType type) {
|
||||
writeOpWithOperandId(CacheOp::GuardType, val);
|
||||
static_assert(sizeof(type) == sizeof(uint8_t), "JSValueType should fit in a byte");
|
||||
|
@ -425,6 +443,9 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
void loadFrameNumActualArgsResult() {
|
||||
writeOp(CacheOp::LoadFrameNumActualArgsResult);
|
||||
}
|
||||
void loadFrameArgumentResult(Int32OperandId index) {
|
||||
writeOpWithOperandId(CacheOp::LoadFrameArgumentResult, index);
|
||||
}
|
||||
void guardNoUnboxedExpando(ObjOperandId obj) {
|
||||
writeOpWithOperandId(CacheOp::GuardNoUnboxedExpando, obj);
|
||||
}
|
||||
|
@ -501,12 +522,20 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
void loadUnboxedArrayLengthResult(ObjOperandId obj) {
|
||||
writeOpWithOperandId(CacheOp::LoadUnboxedArrayLengthResult, obj);
|
||||
}
|
||||
void loadArgumentsObjectArgResult(ObjOperandId obj, Int32OperandId index) {
|
||||
writeOpWithOperandId(CacheOp::LoadArgumentsObjectArgResult, obj);
|
||||
writeOperandId(index);
|
||||
}
|
||||
void loadArgumentsObjectLengthResult(ObjOperandId obj) {
|
||||
writeOpWithOperandId(CacheOp::LoadArgumentsObjectLengthResult, obj);
|
||||
}
|
||||
void loadStringLengthResult(StringOperandId str) {
|
||||
writeOpWithOperandId(CacheOp::LoadStringLengthResult, str);
|
||||
}
|
||||
void loadStringCharResult(StringOperandId str, Int32OperandId index) {
|
||||
writeOpWithOperandId(CacheOp::LoadStringCharResult, str);
|
||||
writeOperandId(index);
|
||||
}
|
||||
void callScriptedGetterResult(ObjOperandId obj, JSFunction* getter) {
|
||||
writeOpWithOperandId(CacheOp::CallScriptedGetterResult, obj);
|
||||
addStubField(uintptr_t(getter), StubField::Type::JSObject);
|
||||
|
@ -561,6 +590,7 @@ class MOZ_RAII CacheIRReader
|
|||
ObjOperandId objOperandId() { return ObjOperandId(buffer_.readByte()); }
|
||||
StringOperandId stringOperandId() { return StringOperandId(buffer_.readByte()); }
|
||||
SymbolOperandId symbolOperandId() { return SymbolOperandId(buffer_.readByte()); }
|
||||
Int32OperandId int32OperandId() { return Int32OperandId(buffer_.readByte()); }
|
||||
|
||||
uint32_t stubOffset() { return buffer_.readByte() * sizeof(uintptr_t); }
|
||||
GuardClassKind guardClassKind() { return GuardClassKind(buffer_.readByte()); }
|
||||
|
@ -623,8 +653,12 @@ class MOZ_RAII GetPropIRGenerator
|
|||
bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id);
|
||||
|
||||
bool tryAttachPrimitive(ValOperandId valId, HandleId id);
|
||||
bool tryAttachStringChar(ValOperandId valId, ValOperandId indexId);
|
||||
bool tryAttachStringLength(ValOperandId valId, HandleId id);
|
||||
bool tryAttachMagicArguments(ValOperandId valId, HandleId id);
|
||||
bool tryAttachMagicArgumentsName(ValOperandId valId, HandleId id);
|
||||
|
||||
bool tryAttachMagicArgument(ValOperandId valId, ValOperandId indexId);
|
||||
bool tryAttachArgumentsObjectArg(HandleObject obj, ObjOperandId objId, ValOperandId indexId);
|
||||
|
||||
ValOperandId getElemKeyValueId() const {
|
||||
MOZ_ASSERT(cacheKind_ == CacheKind::GetElem);
|
||||
|
|
|
@ -1505,6 +1505,11 @@ IonBuilder::visitBlock(const CFGBlock* cfgblock, MBasicBlock* mblock)
|
|||
if (mblock->pc() && script()->hasScriptCounts())
|
||||
mblock->setHitCount(script()->getHitCount(mblock->pc()));
|
||||
|
||||
// Optimization to move a predecessor that only has this block as successor
|
||||
// just before this block.
|
||||
if (mblock->numPredecessors() == 1 && mblock->getPredecessor(0)->numSuccessors() == 1)
|
||||
graph().moveBlockToEnd(mblock->getPredecessor(0));
|
||||
|
||||
if (!setCurrentAndSpecializePhis(mblock))
|
||||
return false;
|
||||
graph().addBlock(mblock);
|
||||
|
@ -2846,6 +2851,9 @@ IonBuilder::visitTest(CFGTest* test)
|
|||
return false;
|
||||
filterBlock->end(MGoto::New(alloc(), ifFalse));
|
||||
|
||||
if (filterBlock->pc() && script()->hasScriptCounts())
|
||||
filterBlock->setHitCount(script()->getHitCount(filterBlock->pc()));
|
||||
|
||||
blockWorklist[test->falseBranch()->id()] = ifFalse;
|
||||
|
||||
current = nullptr;
|
||||
|
@ -3079,6 +3087,9 @@ IonBuilder::visitTableSwitch(CFGTableSwitch* cfgIns)
|
|||
}
|
||||
graph().addBlock(caseBlock);
|
||||
|
||||
if (caseBlock->pc() && script()->hasScriptCounts())
|
||||
caseBlock->setHitCount(script()->getHitCount(caseBlock->pc()));
|
||||
|
||||
MBasicBlock* merge = newBlock(caseBlock, cfgblock->startPc());
|
||||
if (!merge)
|
||||
return false;
|
||||
|
|
|
@ -133,6 +133,7 @@ MSG_DEF(JSMSG_INVALID_NORMALIZE_FORM, 0, JSEXN_RANGEERR, "form must be one of '
|
|||
MSG_DEF(JSMSG_NEGATIVE_REPETITION_COUNT, 0, JSEXN_RANGEERR, "repeat count must be non-negative")
|
||||
MSG_DEF(JSMSG_NOT_A_CODEPOINT, 1, JSEXN_RANGEERR, "{0} is not a valid code point")
|
||||
MSG_DEF(JSMSG_RESULTING_STRING_TOO_LARGE, 0, JSEXN_RANGEERR, "repeat count must be less than infinity and not overflow maximum string size")
|
||||
MSG_DEF(JSMSG_DEPRECATED_STRING_METHOD, 2, JSEXN_WARN, "String.{0} is deprecated; use String.prototype.{1} instead")
|
||||
|
||||
// Number
|
||||
MSG_DEF(JSMSG_BAD_RADIX, 0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36")
|
||||
|
|
|
@ -55,6 +55,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
|
|||
marked(true),
|
||||
warnedAboutExprClosure(false),
|
||||
warnedAboutForEach(false),
|
||||
warnedAboutStringGenericsMethods(0),
|
||||
#ifdef DEBUG
|
||||
firedOnNewGlobalObject(false),
|
||||
#endif
|
||||
|
|
|
@ -361,6 +361,7 @@ struct JSCompartment
|
|||
bool marked;
|
||||
bool warnedAboutExprClosure;
|
||||
bool warnedAboutForEach;
|
||||
uint32_t warnedAboutStringGenericsMethods;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool firedOnNewGlobalObject;
|
||||
|
@ -882,6 +883,7 @@ struct JSCompartment
|
|||
// NO LONGER USING 8
|
||||
// NO LONGER USING 9
|
||||
DeprecatedBlockScopeFunRedecl = 10,
|
||||
DeprecatedStringGenerics = 11,
|
||||
DeprecatedLanguageExtensionCount
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
var BUGNUMBER = 1322319;
|
||||
var summary = "RegExp.prototype.split should throw if RegRxp.prototype.flags is deleted."
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
delete RegExp.prototype.flags;
|
||||
|
||||
assertThrowsInstanceOf(() => "aaaaa".split(/a/), SyntaxError);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,63 @@
|
|||
// |reftest| skip-if(!xulRuntime.shell)
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Warn once for each String generics method.
|
||||
|
||||
var methods = {
|
||||
charAt: ["", 0],
|
||||
charCodeAt: ["", 0],
|
||||
concat: ["", ""],
|
||||
endsWith: ["", ""],
|
||||
includes: ["", ""],
|
||||
indexOf: ["", ""],
|
||||
lastIndexOf: ["", ""],
|
||||
localeCompare: ["", ""],
|
||||
match: ["", ""],
|
||||
normalize: [""],
|
||||
replace: ["", ""],
|
||||
search: ["", ""],
|
||||
slice: ["", 0],
|
||||
split: ["", ""],
|
||||
startsWith: ["", ""],
|
||||
substr: ["", 0],
|
||||
substring: ["", 0],
|
||||
toLowerCase: [""],
|
||||
toLocaleLowerCase: [""],
|
||||
toLocaleUpperCase: [""],
|
||||
toUpperCase: [""],
|
||||
trim: [""],
|
||||
trimLeft: [""],
|
||||
trimRight: [""]
|
||||
};
|
||||
|
||||
for (var name in methods) {
|
||||
var args = methods[name];
|
||||
|
||||
// String.normalize not available on every platform.
|
||||
if (name === "normalize" && !(name in String.prototype))
|
||||
continue;
|
||||
|
||||
enableLastWarning();
|
||||
|
||||
String[name].apply(null, args);
|
||||
|
||||
var warning = getLastWarning();
|
||||
assertEq(warning !== null, true, "warning should be emitted for " + name);
|
||||
assertEq(warning.name, "Warning");
|
||||
assertEq(warning.message.indexOf(name) !== -1, true,
|
||||
"warning should mention " + name);
|
||||
|
||||
clearLastWarning();
|
||||
|
||||
String[name].apply(null, args);
|
||||
|
||||
warning = getLastWarning();
|
||||
assertEq(warning, null, "warning shouldn't be emitted for 2nd call to " + name);
|
||||
|
||||
disableLastWarning();
|
||||
}
|
||||
|
||||
if (typeof reportCompare === 'function')
|
||||
reportCompare(0, 0);
|
|
@ -1904,6 +1904,46 @@ intrinsic_AddContentTelemetry(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_WarnDeprecatedStringMethod(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 2);
|
||||
MOZ_ASSERT(args[0].isInt32());
|
||||
MOZ_ASSERT(args[1].isString());
|
||||
|
||||
uint32_t id = uint32_t(args[0].toInt32());
|
||||
MOZ_ASSERT(id < STRING_GENERICS_METHODS_LIMIT);
|
||||
|
||||
NonBuiltinScriptFrameIter iter(cx);
|
||||
if (!iter.done()) {
|
||||
const char* filename = iter.filename();
|
||||
iter.compartment()->addTelemetry(filename, JSCompartment::DeprecatedStringGenerics);
|
||||
}
|
||||
|
||||
uint32_t mask = (1 << id);
|
||||
if (!(cx->compartment()->warnedAboutStringGenericsMethods & mask)) {
|
||||
JSFlatString* name = args[1].toString()->ensureFlat(cx);
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
AutoStableStringChars stableChars(cx);
|
||||
if (!stableChars.initTwoByte(cx, name))
|
||||
return false;
|
||||
const char16_t* nameChars = stableChars.twoByteRange().begin().get();
|
||||
|
||||
if (!JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_WARNING, GetErrorMessage, nullptr,
|
||||
JSMSG_DEPRECATED_STRING_METHOD, nameChars, nameChars))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
cx->compartment()->warnedAboutStringGenericsMethods |= mask;
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_ConstructFunction(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -2513,6 +2553,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
JS_INLINABLE_FN("StringSplitString", intrinsic_StringSplitString, 2, 0,
|
||||
IntrinsicStringSplitString),
|
||||
JS_FN("StringSplitStringLimit", intrinsic_StringSplitStringLimit, 3, 0),
|
||||
JS_FN("WarnDeprecatedStringMethod", intrinsic_WarnDeprecatedStringMethod, 2, 0),
|
||||
|
||||
// See builtin/RegExp.h for descriptions of the regexp_* functions.
|
||||
JS_FN("regexp_exec_no_statics", regexp_exec_no_statics, 2,0),
|
||||
|
|
|
@ -278,13 +278,14 @@ TraceLoggerThread::disable(bool force, const char* error)
|
|||
}
|
||||
|
||||
const char*
|
||||
TraceLoggerThread::eventText(uint32_t id)
|
||||
TraceLoggerThread::maybeEventText(uint32_t id)
|
||||
{
|
||||
if (id < TraceLogger_Last)
|
||||
return TLTextIdString(static_cast<TraceLoggerTextId>(id));
|
||||
|
||||
TextIdHashMap::Ptr p = textIdPayloads.lookup(id);
|
||||
MOZ_ASSERT(p);
|
||||
if (!p)
|
||||
return nullptr;
|
||||
|
||||
return p->value()->string();
|
||||
}
|
||||
|
@ -570,7 +571,10 @@ TraceLoggerThread::stopEvent(uint32_t id)
|
|||
MOZ_ASSERT(prev >= TraceLogger_Last);
|
||||
} else if (id >= TraceLogger_Last) {
|
||||
MOZ_ASSERT(prev >= TraceLogger_Last);
|
||||
MOZ_ASSERT_IF(prev != id, strcmp(eventText(id), eventText(prev)) == 0);
|
||||
if (prev != id) {
|
||||
// Ignore if the text has been flushed already.
|
||||
MOZ_ASSERT_IF(maybeEventText(prev), strcmp(eventText(id), eventText(prev)) == 0);
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(id == prev);
|
||||
}
|
||||
|
|
|
@ -260,7 +260,14 @@ class TraceLoggerThread
|
|||
return true;
|
||||
}
|
||||
|
||||
const char* eventText(uint32_t id);
|
||||
private:
|
||||
const char* maybeEventText(uint32_t id);
|
||||
public:
|
||||
const char* eventText(uint32_t id) {
|
||||
const char* text = maybeEventText(id);
|
||||
MOZ_ASSERT(text);
|
||||
return text;
|
||||
};
|
||||
bool textIdIsScriptEvent(uint32_t id);
|
||||
|
||||
// The createTextId functions map a unique input to a logger ID.
|
||||
|
|
|
@ -3173,6 +3173,8 @@ nsLayoutUtils::GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
|
|||
builder.SetDescendIntoSubdocuments(false);
|
||||
}
|
||||
|
||||
builder.SetHitTestShouldStopAtFirstOpaque(aFlags & ONLY_VISIBLE);
|
||||
|
||||
builder.EnterPresShell(aFrame);
|
||||
aFrame->BuildDisplayListForStackingContext(&builder, aRect, &list);
|
||||
builder.LeavePresShell(aFrame, nullptr);
|
||||
|
@ -3188,7 +3190,6 @@ nsLayoutUtils::GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
|
|||
#endif
|
||||
|
||||
nsDisplayItem::HitTestState hitTestState;
|
||||
builder.SetHitTestShouldStopAtFirstOpaque(aFlags & ONLY_VISIBLE);
|
||||
list.HitTest(&builder, aRect, &hitTestState, &aOutFrames);
|
||||
list.DeleteAll();
|
||||
return NS_OK;
|
||||
|
|
|
@ -825,7 +825,7 @@ public:
|
|||
* frames under the area of a rectangle that receives a mouse event,
|
||||
* or nullptr if there is no such frame.
|
||||
* @param aRect the rect, relative to the frame origin
|
||||
* @param aOutFrames an array to add all the frames found
|
||||
* @param aOutFrames an array to append all the frames found
|
||||
* @param aFlags some combination of FrameForPointFlags
|
||||
*/
|
||||
static nsresult GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
|
||||
|
|
|
@ -119,7 +119,7 @@ nsHTMLButtonControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayListCollection set;
|
||||
|
||||
// Do not allow the child subtree to receive events.
|
||||
if (!isForEventDelivery) {
|
||||
if (!isForEventDelivery || aBuilder->HitTestShouldStopAtFirstOpaque()) {
|
||||
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
|
||||
|
||||
if (ShouldClipPaintingToBorderBox()) {
|
||||
|
|
|
@ -629,7 +629,7 @@ load text-overflow-form-elements.html
|
|||
load text-overflow-iframe.html
|
||||
asserts-if(Android,2-4) asserts-if(!Android,4) load 1225005.html # bug 682647 and bug 448083
|
||||
load 1233191.html
|
||||
asserts(3) load 1271765.html # bug 1319318
|
||||
load 1271765.html
|
||||
asserts(2) load 1272983-1.html # bug 586628
|
||||
asserts(2) load 1272983-2.html # bug 586628
|
||||
load 1275059.html
|
||||
|
|
|
@ -377,7 +377,9 @@ nsVideoFrame::Reflow(nsPresContext* aPresContext,
|
|||
borderPadding.left, borderPadding.top, 0, aStatus);
|
||||
|
||||
if (child->GetContent() == mVideoControls && isBSizeShrinkWrapping) {
|
||||
contentBoxBSize = kidDesiredSize.BSize(myWM);
|
||||
// Resolve our own BSize based on the controls' size in the same axis.
|
||||
contentBoxBSize = myWM.IsOrthogonalTo(wm) ?
|
||||
kidDesiredSize.ISize(wm) : kidDesiredSize.BSize(wm);
|
||||
}
|
||||
|
||||
FinishReflowChild(child, aPresContext,
|
||||
|
|
|
@ -48,7 +48,8 @@
|
|||
#include "nsCSSProps.h"
|
||||
#include "nsCSSValue.h"
|
||||
#include "nsColor.h"
|
||||
#include "nsStyleSet.h"
|
||||
#include "mozilla/StyleSetHandle.h"
|
||||
#include "mozilla/StyleSetHandleInlines.h"
|
||||
#include "nsStyleUtil.h"
|
||||
#include "nsQueryObject.h"
|
||||
|
||||
|
@ -77,7 +78,7 @@ inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength,
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aDocument);
|
||||
|
||||
nsTArray<RefPtr<CSSStyleSheet>> sheets;
|
||||
nsTArray<RefPtr<StyleSheet>> sheets;
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
|
||||
MOZ_ASSERT(document);
|
||||
|
@ -85,15 +86,8 @@ inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength,
|
|||
// Get the agent, then user and finally xbl sheets in the style set.
|
||||
nsIPresShell* presShell = document->GetShell();
|
||||
|
||||
if (presShell && presShell->StyleSet()->IsServo()) {
|
||||
// XXXheycam ServoStyleSets don't have the ability to expose their
|
||||
// sheets in a script-accessible way yet.
|
||||
NS_ERROR("stylo: ServoStyleSets cannot expose their sheets to script yet");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (presShell) {
|
||||
nsStyleSet* styleSet = presShell->StyleSet()->AsGecko();
|
||||
StyleSetHandle styleSet = presShell->StyleSet();
|
||||
SheetType sheetType = SheetType::Agent;
|
||||
for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) {
|
||||
sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i));
|
||||
|
@ -102,24 +96,26 @@ inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength,
|
|||
for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) {
|
||||
sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i));
|
||||
}
|
||||
AutoTArray<CSSStyleSheet*, 32> xblSheetArray;
|
||||
styleSet->AppendAllXBLStyleSheets(xblSheetArray);
|
||||
if (styleSet->IsGecko()) {
|
||||
AutoTArray<CSSStyleSheet*, 32> xblSheetArray;
|
||||
styleSet->AsGecko()->AppendAllXBLStyleSheets(xblSheetArray);
|
||||
|
||||
// The XBL stylesheet array will quite often be full of duplicates. Cope:
|
||||
nsTHashtable<nsPtrHashKey<CSSStyleSheet>> sheetSet;
|
||||
for (CSSStyleSheet* sheet : xblSheetArray) {
|
||||
if (!sheetSet.Contains(sheet)) {
|
||||
sheetSet.PutEntry(sheet);
|
||||
sheets.AppendElement(sheet);
|
||||
// The XBL stylesheet array will quite often be full of duplicates. Cope:
|
||||
nsTHashtable<nsPtrHashKey<CSSStyleSheet>> sheetSet;
|
||||
for (CSSStyleSheet* sheet : xblSheetArray) {
|
||||
if (!sheetSet.Contains(sheet)) {
|
||||
sheetSet.PutEntry(sheet);
|
||||
sheets.AppendElement(sheet);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("stylo: XBL style sheets not supported yet");
|
||||
}
|
||||
}
|
||||
|
||||
// Get the document sheets.
|
||||
for (int32_t i = 0; i < document->GetNumberOfStyleSheets(); i++) {
|
||||
// XXXheycam ServoStyleSets don't have the ability to expose their
|
||||
// sheets in a script-accessible way yet.
|
||||
sheets.AppendElement(document->GetStyleSheetAt(i)->AsGecko());
|
||||
sheets.AppendElement(document->GetStyleSheetAt(i));
|
||||
}
|
||||
|
||||
nsISupports** ret = static_cast<nsISupports**>(moz_xmalloc(sheets.Length() *
|
||||
|
|
|
@ -2965,6 +2965,7 @@ var gCSSProperties = {
|
|||
"ruby-base-container",
|
||||
"ruby-text",
|
||||
"ruby-text-container",
|
||||
"contents",
|
||||
"none"
|
||||
],
|
||||
invalid_values: []
|
||||
|
@ -6725,8 +6726,6 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
|
|||
};
|
||||
}
|
||||
|
||||
gCSSProperties["display"].other_values.push("contents");
|
||||
|
||||
if (IsCSSPropertyPrefEnabled("layout.css.contain.enabled")) {
|
||||
gCSSProperties["contain"] = {
|
||||
domProp: "contain",
|
||||
|
|
|
@ -14,27 +14,14 @@ using namespace std;
|
|||
#include "mozilla/SyncRunnable.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include <MediaConduitInterface.h>
|
||||
#include "GmpVideoCodec.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "FakeMediaStreamsImpl.h"
|
||||
#include "FakeLogging.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "runnable_utils.h"
|
||||
#include "signaling/src/common/EncodingConstraints.h"
|
||||
|
||||
#include "FakeIPC.h"
|
||||
#include "FakeIPC.cpp"
|
||||
#include "prmem.h"
|
||||
|
||||
#define GTEST_HAS_RTTI 0
|
||||
#include "gtest/gtest.h"
|
||||
#include "gtest_utils.h"
|
||||
|
||||
nsCOMPtr<nsIThread> gMainThread;
|
||||
nsCOMPtr<nsIThread> gGtestThread;
|
||||
bool gTestsComplete = false;
|
||||
|
||||
#include "mtransport_test_utils.h"
|
||||
MtransportTestUtils *test_utils;
|
||||
|
||||
//Video Frame Color
|
||||
const int COLOR = 0x80; //Gray
|
||||
|
@ -128,7 +115,7 @@ int numFrames;
|
|||
* A Dummy AudioConduit Tester
|
||||
* The test reads PCM samples of a standard test file and
|
||||
* passws to audio-conduit for encoding, RTPfication and
|
||||
* decoding ebery 10 milliseconds.
|
||||
* decoding every 10 milliseconds.
|
||||
* This decoded samples are read-off the conduit for writing
|
||||
* into output audio file in PCM format.
|
||||
*/
|
||||
|
@ -136,7 +123,7 @@ class AudioSendAndReceive
|
|||
{
|
||||
public:
|
||||
static const unsigned int PLAYOUT_SAMPLE_FREQUENCY; //default is 16000
|
||||
static const unsigned int PLAYOUT_SAMPLE_LENGTH; //default is 160000
|
||||
static const unsigned int PLAYOUT_SAMPLE_LENGTH; //default is 160
|
||||
|
||||
AudioSendAndReceive()
|
||||
{
|
||||
|
@ -173,7 +160,7 @@ private:
|
|||
};
|
||||
|
||||
const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_FREQUENCY = 16000;
|
||||
const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_LENGTH = 160000;
|
||||
const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_LENGTH = 160;
|
||||
|
||||
int AudioSendAndReceive::WriteWaveHeader(int rate, int channels, FILE* outFile)
|
||||
{
|
||||
|
@ -262,12 +249,7 @@ void AudioSendAndReceive::GenerateMusic(short* buf, int len)
|
|||
a1=b1=a2=b2=0;
|
||||
c1=c2=d1=d2=0;
|
||||
j=0;
|
||||
/*60ms silence */
|
||||
for(i=0;i<2880;i++)
|
||||
{
|
||||
buf[i*2]=buf[(i*2)+1]=0;
|
||||
}
|
||||
for(i=2880;i<len-1;i+=2)
|
||||
for(i=0;i<len-1;i+=2)
|
||||
{
|
||||
int32_t r;
|
||||
int32_t v1,v2;
|
||||
|
@ -294,7 +276,7 @@ void AudioSendAndReceive::GenerateAndReadSamples()
|
|||
auto audioOutput = mozilla::MakeUnique<int16_t []>(PLAYOUT_SAMPLE_LENGTH);
|
||||
short* inbuf;
|
||||
int sampleLengthDecoded = 0;
|
||||
unsigned int SAMPLES = (PLAYOUT_SAMPLE_FREQUENCY * 10); //10 seconds
|
||||
unsigned int SAMPLES = (PLAYOUT_SAMPLE_FREQUENCY / 100); //10 milliseconds
|
||||
int CHANNELS = 1; //mono audio
|
||||
int sampleLengthInBytes = sizeof(int16_t) * PLAYOUT_SAMPLE_LENGTH;
|
||||
//generated audio buffer
|
||||
|
@ -337,7 +319,6 @@ void AudioSendAndReceive::GenerateAndReadSamples()
|
|||
}
|
||||
|
||||
numSamplesReadFromInput += PLAYOUT_SAMPLE_LENGTH;
|
||||
inbuf += PLAYOUT_SAMPLE_LENGTH;
|
||||
|
||||
mSession->SendAudioFrame(audioInput.get(),
|
||||
PLAYOUT_SAMPLE_LENGTH,
|
||||
|
@ -366,7 +347,7 @@ void AudioSendAndReceive::GenerateAndReadSamples()
|
|||
|
||||
/**
|
||||
* Dummy Video Target for the conduit
|
||||
* This class acts as renderer attached to the video conuit
|
||||
* This class acts as renderer attached to the video conduit
|
||||
* As of today we just verify if the frames rendered are exactly
|
||||
* the same as frame inserted at the first place
|
||||
*/
|
||||
|
@ -509,8 +490,9 @@ private:
|
|||
bool mAudio, mVideo;
|
||||
};
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace {
|
||||
namespace test {
|
||||
|
||||
class TransportConduitTest : public ::testing::Test
|
||||
{
|
||||
|
@ -525,13 +507,6 @@ class TransportConduitTest : public ::testing::Test
|
|||
|
||||
~TransportConduitTest()
|
||||
{
|
||||
mozilla::SyncRunnable::DispatchToThread(gMainThread,
|
||||
mozilla::WrapRunnable(
|
||||
this,
|
||||
&TransportConduitTest::SelfDestruct));
|
||||
}
|
||||
|
||||
void SelfDestruct() {
|
||||
mAudioSession = nullptr;
|
||||
mAudioSession2 = nullptr;
|
||||
mAudioTransport = nullptr;
|
||||
|
@ -547,19 +522,13 @@ class TransportConduitTest : public ::testing::Test
|
|||
{
|
||||
//get pointer to AudioSessionConduit
|
||||
int err=0;
|
||||
mozilla::SyncRunnable::DispatchToThread(gMainThread,
|
||||
WrapRunnableNMRet(&mAudioSession,
|
||||
&mozilla::AudioSessionConduit::Create));
|
||||
if( !mAudioSession ) {
|
||||
mAudioSession = mozilla::AudioSessionConduit::Create();
|
||||
if( !mAudioSession )
|
||||
ASSERT_NE(mAudioSession, (void*)nullptr);
|
||||
}
|
||||
|
||||
mozilla::SyncRunnable::DispatchToThread(gMainThread,
|
||||
WrapRunnableNMRet(&mAudioSession2,
|
||||
&mozilla::AudioSessionConduit::Create));
|
||||
if( !mAudioSession2 ) {
|
||||
mAudioSession2 = mozilla::AudioSessionConduit::Create();
|
||||
if( !mAudioSession2 )
|
||||
ASSERT_NE(mAudioSession2, (void*)nullptr);
|
||||
}
|
||||
|
||||
WebrtcMediaTransport* xport = new WebrtcMediaTransport();
|
||||
ASSERT_NE(xport, (void*)nullptr);
|
||||
|
@ -600,9 +569,7 @@ class TransportConduitTest : public ::testing::Test
|
|||
cerr << " ******************************************************** " << endl;
|
||||
cerr << " Generating Audio Samples " << endl;
|
||||
cerr << " ******************************************************** " << endl;
|
||||
PR_Sleep(PR_SecondsToInterval(2));
|
||||
audioTester.GenerateAndReadSamples();
|
||||
PR_Sleep(PR_SecondsToInterval(2));
|
||||
cerr << " ******************************************************** " << endl;
|
||||
cerr << " Input Audio File " << iAudiofilename << endl;
|
||||
cerr << " Output Audio File " << oAudiofilename << endl;
|
||||
|
@ -610,28 +577,18 @@ class TransportConduitTest : public ::testing::Test
|
|||
}
|
||||
|
||||
//2. Dump audio samples to dummy external transport
|
||||
void TestDummyVideoAndTransport(bool send_vp8 = true, const char *source_file = nullptr)
|
||||
void TestDummyVideoAndTransport(const char *source_file = nullptr)
|
||||
{
|
||||
int err = 0;
|
||||
//get pointer to VideoSessionConduit
|
||||
mozilla::SyncRunnable::DispatchToThread(gMainThread,
|
||||
WrapRunnableNMRet(&mVideoSession,
|
||||
&mozilla::VideoSessionConduit::Create));
|
||||
if( !mVideoSession ) {
|
||||
mVideoSession = VideoSessionConduit::Create();
|
||||
if( !mVideoSession )
|
||||
ASSERT_NE(mVideoSession, (void*)nullptr);
|
||||
}
|
||||
|
||||
// This session is for other one
|
||||
mozilla::SyncRunnable::DispatchToThread(gMainThread,
|
||||
WrapRunnableNMRet(&mVideoSession2,
|
||||
&mozilla::VideoSessionConduit::Create));
|
||||
if( !mVideoSession2 ) {
|
||||
// This session is for other one
|
||||
mVideoSession2 = VideoSessionConduit::Create();
|
||||
if( !mVideoSession2 )
|
||||
ASSERT_NE(mVideoSession2,(void*)nullptr);
|
||||
}
|
||||
|
||||
if (!send_vp8) {
|
||||
SetGmpCodecs();
|
||||
}
|
||||
|
||||
mVideoRenderer = new DummyVideoTarget();
|
||||
ASSERT_NE(mVideoRenderer, (void*)nullptr);
|
||||
|
@ -659,15 +616,13 @@ class TransportConduitTest : public ::testing::Test
|
|||
rcvCodecList.push_back(&cinst1);
|
||||
rcvCodecList.push_back(&cinst2);
|
||||
|
||||
err = mVideoSession->ConfigureSendMediaCodec(
|
||||
send_vp8 ? &cinst1 : &cinst2);
|
||||
err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
|
||||
|
||||
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
|
||||
err = mVideoSession->StartTransmitting();
|
||||
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
|
||||
|
||||
err = mVideoSession2->ConfigureSendMediaCodec(
|
||||
send_vp8 ? &cinst1 : &cinst2);
|
||||
err = mVideoSession2->ConfigureSendMediaCodec(&cinst1);
|
||||
err = mVideoSession2->StartTransmitting();
|
||||
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
|
||||
|
||||
|
@ -679,10 +634,8 @@ class TransportConduitTest : public ::testing::Test
|
|||
cerr << " *************************************************" << endl;
|
||||
cerr << " Starting the Video Sample Generation " << endl;
|
||||
cerr << " *************************************************" << endl;
|
||||
PR_Sleep(PR_SecondsToInterval(2));
|
||||
videoTester.Init(mVideoSession);
|
||||
videoTester.GenerateAndReadSamples();
|
||||
PR_Sleep(PR_SecondsToInterval(2));
|
||||
|
||||
cerr << " **************************************************" << endl;
|
||||
cerr << " Done With The Testing " << endl;
|
||||
|
@ -697,19 +650,10 @@ class TransportConduitTest : public ::testing::Test
|
|||
cerr << " Done With The Testing " << endl;
|
||||
|
||||
cerr << " **************************************************" << endl;
|
||||
|
||||
ASSERT_EQ(0, vidStatsGlobal.numFramesRenderedWrongly);
|
||||
if (send_vp8) {
|
||||
ASSERT_EQ(vidStatsGlobal.numRawFramesInserted,
|
||||
vidStatsGlobal.numFramesRenderedSuccessfully);
|
||||
}
|
||||
else {
|
||||
// Allow some fudge because there seems to be some buffering.
|
||||
// TODO(ekr@rtfm.com): Fix this.
|
||||
ASSERT_GE(vidStatsGlobal.numRawFramesInserted,
|
||||
vidStatsGlobal.numFramesRenderedSuccessfully);
|
||||
ASSERT_LE(vidStatsGlobal.numRawFramesInserted,
|
||||
vidStatsGlobal.numFramesRenderedSuccessfully + 2);
|
||||
}
|
||||
ASSERT_EQ(vidStatsGlobal.numRawFramesInserted,
|
||||
vidStatsGlobal.numFramesRenderedSuccessfully);
|
||||
}
|
||||
|
||||
void TestVideoConduitCodecAPI()
|
||||
|
@ -717,12 +661,9 @@ class TransportConduitTest : public ::testing::Test
|
|||
int err = 0;
|
||||
RefPtr<mozilla::VideoSessionConduit> videoSession;
|
||||
//get pointer to VideoSessionConduit
|
||||
mozilla::SyncRunnable::DispatchToThread(gMainThread,
|
||||
WrapRunnableNMRet(&videoSession,
|
||||
&mozilla::VideoSessionConduit::Create));
|
||||
if( !videoSession ) {
|
||||
videoSession = VideoSessionConduit::Create();
|
||||
if( !videoSession )
|
||||
ASSERT_NE(videoSession, (void*)nullptr);
|
||||
}
|
||||
|
||||
//Test Configure Recv Codec APIS
|
||||
cerr << " *************************************************" << endl;
|
||||
|
@ -742,12 +683,11 @@ class TransportConduitTest : public ::testing::Test
|
|||
rcvCodecList.push_back(&cinst1);
|
||||
rcvCodecList.push_back(&cinst2);
|
||||
err = videoSession->ConfigureRecvMediaCodecs(rcvCodecList);
|
||||
EXPECT_NE(err,mozilla::kMediaConduitNoError);
|
||||
EXPECT_EQ(err, mozilla::kMediaConduitNoError);
|
||||
rcvCodecList.pop_back();
|
||||
rcvCodecList.pop_back();
|
||||
|
||||
|
||||
PR_Sleep(PR_SecondsToInterval(2));
|
||||
cerr << " *************************************************" << endl;
|
||||
cerr << " 2. Codec With Invalid Payload Names " << endl;
|
||||
cerr << " *************************************************" << endl;
|
||||
|
@ -766,7 +706,6 @@ class TransportConduitTest : public ::testing::Test
|
|||
rcvCodecList.pop_back();
|
||||
|
||||
|
||||
PR_Sleep(PR_SecondsToInterval(2));
|
||||
cerr << " *************************************************" << endl;
|
||||
cerr << " 3. Null Codec Parameter " << endl;
|
||||
cerr << " *************************************************" << endl;
|
||||
|
@ -791,7 +730,7 @@ class TransportConduitTest : public ::testing::Test
|
|||
err = videoSession->StartTransmitting();
|
||||
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
|
||||
err = videoSession->ConfigureSendMediaCodec(&cinst1);
|
||||
EXPECT_EQ(mozilla::kMediaConduitCodecInUse, err);
|
||||
EXPECT_EQ(mozilla::kMediaConduitNoError, err);
|
||||
err = videoSession->StartTransmitting();
|
||||
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
|
||||
|
||||
|
@ -810,11 +749,6 @@ class TransportConduitTest : public ::testing::Test
|
|||
|
||||
err = videoSession->ConfigureSendMediaCodec(nullptr);
|
||||
EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
|
||||
|
||||
mozilla::SyncRunnable::DispatchToThread(gMainThread,
|
||||
WrapRunnable(
|
||||
videoSession.forget().take(),
|
||||
&mozilla::VideoSessionConduit::Release));
|
||||
}
|
||||
|
||||
void DumpMaxFs(int orig_width, int orig_height, int max_fs,
|
||||
|
@ -833,12 +767,9 @@ class TransportConduitTest : public ::testing::Test
|
|||
int err = 0;
|
||||
|
||||
// Get pointer to VideoSessionConduit.
|
||||
mozilla::SyncRunnable::DispatchToThread(gMainThread,
|
||||
WrapRunnableNMRet(&mVideoSession,
|
||||
&mozilla::VideoSessionConduit::Create));
|
||||
if( !mVideoSession ) {
|
||||
mVideoSession = VideoSessionConduit::Create();
|
||||
if( !mVideoSession )
|
||||
ASSERT_NE(mVideoSession, (void*)nullptr);
|
||||
}
|
||||
|
||||
mozilla::EncodingConstraints constraints;
|
||||
constraints.maxFs = max_fs;
|
||||
|
@ -902,7 +833,7 @@ class TransportConduitTest : public ::testing::Test
|
|||
GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
|
||||
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
|
||||
ASSERT_EQ(width, 768);
|
||||
ASSERT_EQ(height, 26);
|
||||
ASSERT_EQ(height, 25);
|
||||
|
||||
// Small max-fs.
|
||||
cerr << "Test small max-fs (case 1)" << endl;
|
||||
|
@ -921,7 +852,7 @@ class TransportConduitTest : public ::testing::Test
|
|||
max_fs = 1;
|
||||
GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
|
||||
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
|
||||
ASSERT_EQ(width, 2);
|
||||
ASSERT_EQ(width, 1);
|
||||
ASSERT_EQ(height, 16);
|
||||
|
||||
// Small max-fs.
|
||||
|
@ -932,7 +863,7 @@ class TransportConduitTest : public ::testing::Test
|
|||
GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
|
||||
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
|
||||
ASSERT_EQ(width, 48);
|
||||
ASSERT_EQ(height, 8);
|
||||
ASSERT_EQ(height, 7);
|
||||
|
||||
// Small max-fs.
|
||||
cerr << "Test small max-fs (case 4)" << endl;
|
||||
|
@ -969,23 +900,10 @@ class TransportConduitTest : public ::testing::Test
|
|||
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
|
||||
ADD_FAILURE();
|
||||
}
|
||||
if ((width & 1) || (height & 1)) {
|
||||
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
|
||||
ADD_FAILURE();
|
||||
}
|
||||
}
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
void SetGmpCodecs() {
|
||||
mExternalEncoder = mozilla::GmpVideoCodec::CreateEncoder();
|
||||
mExternalDecoder = mozilla::GmpVideoCodec::CreateDecoder();
|
||||
mozilla::EncodingConstraints constraints;
|
||||
mozilla::VideoCodecConfig config(124, "H264", constraints);
|
||||
mVideoSession->SetExternalSendCodec(&config, mExternalEncoder);
|
||||
mVideoSession2->SetExternalRecvCodec(&config, mExternalDecoder);
|
||||
}
|
||||
|
||||
private:
|
||||
//Audio Conduit Test Objects
|
||||
RefPtr<mozilla::AudioSessionConduit> mAudioSession;
|
||||
|
@ -1000,9 +918,6 @@ class TransportConduitTest : public ::testing::Test
|
|||
RefPtr<mozilla::TransportInterface> mVideoTransport;
|
||||
VideoSendAndReceive videoTester;
|
||||
|
||||
mozilla::VideoEncoder* mExternalEncoder;
|
||||
mozilla::VideoDecoder* mExternalDecoder;
|
||||
|
||||
std::string fileToPlay;
|
||||
std::string fileToRecord;
|
||||
std::string iAudiofilename;
|
||||
|
@ -1011,19 +926,17 @@ class TransportConduitTest : public ::testing::Test
|
|||
|
||||
|
||||
// Test 1: Test Dummy External Xport
|
||||
TEST_F(TransportConduitTest, TestDummyAudioWithTransport) {
|
||||
// See Bug 1319121
|
||||
TEST_F(TransportConduitTest, DISABLED_TestDummyAudioWithTransport) {
|
||||
TestDummyAudioAndTransport();
|
||||
}
|
||||
|
||||
// Test 2: Test Dummy External Xport
|
||||
TEST_F(TransportConduitTest, TestDummyVideoWithTransport) {
|
||||
// See Bug 1319121
|
||||
TEST_F(TransportConduitTest, DISABLED_TestDummyVideoWithTransport) {
|
||||
TestDummyVideoAndTransport();
|
||||
}
|
||||
|
||||
TEST_F(TransportConduitTest, TestVideoConduitExternalCodec) {
|
||||
TestDummyVideoAndTransport(false);
|
||||
}
|
||||
|
||||
TEST_F(TransportConduitTest, TestVideoConduitCodecAPI) {
|
||||
TestVideoConduitCodecAPI();
|
||||
}
|
||||
|
@ -1033,65 +946,3 @@ TEST_F(TransportConduitTest, TestVideoConduitMaxFs) {
|
|||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
static int test_result;
|
||||
bool test_finished = false;
|
||||
|
||||
|
||||
|
||||
// This exists to send as an event to trigger shutdown.
|
||||
static void tests_complete() {
|
||||
gTestsComplete = true;
|
||||
}
|
||||
|
||||
// The GTest thread runs this instead of the main thread so it can
|
||||
// do things like ASSERT_TRUE_WAIT which you could not do on the main thread.
|
||||
static int gtest_main(int argc, char **argv) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
int result = RUN_ALL_TESTS();
|
||||
|
||||
// Set the global shutdown flag and tickle the main thread
|
||||
// The main thread did not go through Init() so calling Shutdown()
|
||||
// on it will not work.
|
||||
gMainThread->Dispatch(mozilla::WrapRunnableNM(tests_complete), NS_DISPATCH_SYNC);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// This test can cause intermittent oranges on the builders
|
||||
CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_MEDIACONDUIT_TESTS")
|
||||
|
||||
test_utils = new MtransportTestUtils();
|
||||
|
||||
// Set the main thread global which is this thread.
|
||||
nsIThread *thread;
|
||||
NS_GetMainThread(&thread);
|
||||
gMainThread = thread;
|
||||
|
||||
// Now create the GTest thread and run all of the tests on it
|
||||
// When it is complete it will set gTestsComplete
|
||||
NS_NewNamedThread("gtest_thread", &thread);
|
||||
gGtestThread = thread;
|
||||
|
||||
int result;
|
||||
gGtestThread->Dispatch(
|
||||
mozilla::WrapRunnableNMRet(&result, gtest_main, argc, argv), NS_DISPATCH_NORMAL);
|
||||
|
||||
// Here we handle the event queue for dispatches to the main thread
|
||||
// When the GTest thread is complete it will send one more dispatch
|
||||
// with gTestsComplete == true.
|
||||
while (!gTestsComplete && NS_ProcessNextEvent());
|
||||
|
||||
gGtestThread->Shutdown();
|
||||
|
||||
delete test_utils;
|
||||
return test_result;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -13,12 +13,15 @@ if CONFIG['OS_TARGET'] != 'WINNT' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk' and
|
|||
'/media/mtransport',
|
||||
'/media/webrtc/',
|
||||
'/media/webrtc/signaling/src/common/time_profiling',
|
||||
'/media/webrtc/signaling/src/media-conduit',
|
||||
'/media/webrtc/signaling/src/peerconnection',
|
||||
'/media/webrtc/trunk/',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'jsep_session_unittest.cpp',
|
||||
'jsep_track_unittest.cpp',
|
||||
'mediaconduit_unittests.cpp',
|
||||
'sdp_unittests.cpp',
|
||||
]
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
# TODO: bug 1172551 - get these tests working on iOS
|
||||
if CONFIG['OS_TARGET'] != 'WINNT' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'uikit':
|
||||
GeckoCppUnitTests([
|
||||
'mediaconduit_unittests',
|
||||
'mediapipeline_unittest',
|
||||
'signaling_unittests',
|
||||
])
|
||||
|
|
|
@ -103,12 +103,9 @@ import org.mozilla.gecko.util.EventCallback;
|
|||
import org.mozilla.gecko.util.FloatUtils;
|
||||
import org.mozilla.gecko.util.GamepadUtils;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.IntentUtils;
|
||||
import org.mozilla.gecko.util.MenuUtils;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.PrefUtils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
@ -202,8 +199,7 @@ public class BrowserApp extends GeckoApp
|
|||
OnUrlOpenInBackgroundListener,
|
||||
AnchoredPopup.OnVisibilityChangeListener,
|
||||
ActionModeCompat.Presenter,
|
||||
LayoutInflater.Factory,
|
||||
BundleEventListener {
|
||||
LayoutInflater.Factory {
|
||||
private static final String LOGTAG = "GeckoBrowserApp";
|
||||
|
||||
private static final int TABS_ANIMATION_DURATION = 450;
|
||||
|
@ -726,32 +722,36 @@ public class BrowserApp extends GeckoApp
|
|||
|
||||
mDoorhangerOverlay = findViewById(R.id.doorhanger_overlay);
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener)this,
|
||||
"Gecko:DelayedStartup",
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
"Search:Keyword",
|
||||
"Favicon:CacheLoad",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this,
|
||||
"Menu:Open",
|
||||
"Menu:Update",
|
||||
"Menu:Add",
|
||||
"Menu:Remove",
|
||||
"LightweightTheme:Update",
|
||||
"Search:Keyword",
|
||||
"Tab:Added",
|
||||
"Video:Play");
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener)this,
|
||||
"Video:Play",
|
||||
"CharEncoding:Data",
|
||||
"CharEncoding:State",
|
||||
"Download:AndroidDownloadManager",
|
||||
"Settings:Show",
|
||||
"Updater:Launch",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().registerBackgroundThreadListener(this,
|
||||
"Experiments:GetActive",
|
||||
"Experiments:SetOverride",
|
||||
"Experiments:ClearOverride",
|
||||
"Favicon:CacheLoad",
|
||||
"Feedback:MaybeLater",
|
||||
"Menu:Add",
|
||||
"Menu:Remove",
|
||||
"Sanitize:ClearHistory",
|
||||
"Sanitize:ClearSyncedTabs",
|
||||
"Settings:Show",
|
||||
"Telemetry:Gather",
|
||||
"Updater:Launch",
|
||||
"Website:Metadata");
|
||||
"Download:AndroidDownloadManager",
|
||||
"Website:Metadata",
|
||||
null);
|
||||
|
||||
getAppEventDispatcher().registerUiThreadListener(this, "Prompt:ShowTop");
|
||||
|
||||
|
@ -1430,32 +1430,36 @@ public class BrowserApp extends GeckoApp
|
|||
|
||||
mSearchEngineManager.unregisterListeners();
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener) this,
|
||||
"Gecko:DelayedStartup",
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
|
||||
"Search:Keyword",
|
||||
"Favicon:CacheLoad",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(this,
|
||||
"Menu:Open",
|
||||
"Menu:Update",
|
||||
"Menu:Add",
|
||||
"Menu:Remove",
|
||||
"LightweightTheme:Update",
|
||||
"Search:Keyword",
|
||||
"Tab:Added",
|
||||
"Video:Play");
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener) this,
|
||||
"Video:Play",
|
||||
"CharEncoding:Data",
|
||||
"CharEncoding:State",
|
||||
"Download:AndroidDownloadManager",
|
||||
"Settings:Show",
|
||||
"Updater:Launch",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().unregisterBackgroundThreadListener(this,
|
||||
"Experiments:GetActive",
|
||||
"Experiments:SetOverride",
|
||||
"Experiments:ClearOverride",
|
||||
"Favicon:CacheLoad",
|
||||
"Feedback:MaybeLater",
|
||||
"Menu:Add",
|
||||
"Menu:Remove",
|
||||
"Sanitize:ClearHistory",
|
||||
"Sanitize:ClearSyncedTabs",
|
||||
"Settings:Show",
|
||||
"Telemetry:Gather",
|
||||
"Updater:Launch",
|
||||
"Website:Metadata");
|
||||
"Download:AndroidDownloadManager",
|
||||
"Website:Metadata",
|
||||
null);
|
||||
|
||||
getAppEventDispatcher().unregisterUiThreadListener(this, "Prompt:ShowTop");
|
||||
|
||||
|
@ -1548,25 +1552,6 @@ public class BrowserApp extends GeckoApp
|
|||
alphaAnimator.start();
|
||||
}
|
||||
|
||||
private void handleClearHistory(final boolean clearSearchHistory) {
|
||||
final BrowserDB db = BrowserDB.from(getProfile());
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
db.clearHistory(getContentResolver(), clearSearchHistory);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleClearSyncedTabs() {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FennecTabsRepository.deleteNonLocalClientsAndTabs(getContext());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setToolbarMargin(int margin) {
|
||||
((RelativeLayout.LayoutParams) mGeckoLayout.getLayoutParams()).topMargin = margin;
|
||||
mGeckoLayout.requestLayout();
|
||||
|
@ -1663,29 +1648,21 @@ public class BrowserApp extends GeckoApp
|
|||
|
||||
@Override
|
||||
void toggleChrome(final boolean aShow) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (aShow) {
|
||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mBrowserChrome.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (aShow) {
|
||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mBrowserChrome.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
super.toggleChrome(aShow);
|
||||
}
|
||||
|
||||
@Override
|
||||
void focusChrome() {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
||||
mActionBarFlipper.requestFocusFromTouch();
|
||||
}
|
||||
});
|
||||
mBrowserChrome.setVisibility(View.VISIBLE);
|
||||
mActionBarFlipper.requestFocusFromTouch();
|
||||
|
||||
super.focusChrome();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1707,6 +1684,124 @@ public class BrowserApp extends GeckoApp
|
|||
public void handleMessage(final String event, final GeckoBundle message,
|
||||
final EventCallback callback) {
|
||||
switch (event) {
|
||||
case "Gecko:Ready":
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this, "Gecko:DelayedStartup");
|
||||
|
||||
// Handle this message in GeckoApp, but also enable the Settings
|
||||
// menuitem, which is specific to BrowserApp.
|
||||
super.handleMessage(event, message, callback);
|
||||
|
||||
final Menu menu = mMenu;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (menu != null) {
|
||||
menu.findItem(R.id.settings).setEnabled(true);
|
||||
menu.findItem(R.id.help).setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Display notification for Mozilla data reporting, if data should be collected.
|
||||
if (AppConstants.MOZ_DATA_REPORTING &&
|
||||
Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
|
||||
DataReportingNotification.checkAndNotifyPolicy(GeckoAppShell.getContext());
|
||||
}
|
||||
break;
|
||||
|
||||
case "Gecko:DelayedStartup":
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(this, "Gecko:DelayedStartup");
|
||||
|
||||
// Force tabs panel inflation once the initial pageload is finished.
|
||||
ensureTabsPanelExists();
|
||||
|
||||
if (AppConstants.NIGHTLY_BUILD && mZoomedView == null) {
|
||||
ViewStub stub = (ViewStub) findViewById(R.id.zoomed_view_stub);
|
||||
mZoomedView = (ZoomedView) stub.inflate();
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_MEDIA_PLAYER) {
|
||||
// Check if the fragment is already added. This should never be true
|
||||
// here, but this is a nice safety check. If casting is disabled,
|
||||
// these classes aren't built. We use reflection to initialize them.
|
||||
final Class<?> mediaManagerClass = getMediaPlayerManager();
|
||||
|
||||
if (mediaManagerClass != null) {
|
||||
try {
|
||||
final String tag = "";
|
||||
mediaManagerClass.getDeclaredField("MEDIA_PLAYER_TAG").get(tag);
|
||||
Log.i(LOGTAG, "Found tag " + tag);
|
||||
final Fragment frag = getSupportFragmentManager().findFragmentByTag(tag);
|
||||
if (frag == null) {
|
||||
final Method getInstance = mediaManagerClass.getMethod(
|
||||
"getInstance", (Class[]) null);
|
||||
final Fragment mpm = (Fragment) getInstance.invoke(null);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.disallowAddToBackStack().add(mpm, tag).commit();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.e(LOGTAG, "Error initializing media manager", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED &&
|
||||
Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
|
||||
// Start (this acts as ping if started already) the stumbler lib; if
|
||||
// the stumbler has queued data it will upload it. Stumbler operates
|
||||
// on its own thread, and startup impact is further minimized by
|
||||
// delaying work (such as upload) a few seconds. Avoid any potential
|
||||
// startup CPU/thread contention by delaying the pref broadcast.
|
||||
GeckoPreferences.broadcastStumblerPref(BrowserApp.this);
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE) {
|
||||
// TODO: Better scheduling of sync action (Bug 1257492)
|
||||
DownloadContentService.startSync(this);
|
||||
DownloadContentService.startVerification(this);
|
||||
}
|
||||
|
||||
FeedService.setup(this);
|
||||
break;
|
||||
|
||||
case "Menu:Open":
|
||||
if (mBrowserToolbar.isEditing()) {
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
openOptionsMenu();
|
||||
break;
|
||||
|
||||
case "Menu:Update":
|
||||
updateAddonMenuItem(message.getInt("id"), message.getBundle("options"));
|
||||
break;
|
||||
|
||||
case "Menu:Add":
|
||||
final MenuItemInfo info = new MenuItemInfo();
|
||||
info.label = message.getString("name");
|
||||
info.id = message.getInt("id") + ADDON_MENU_OFFSET;
|
||||
info.checked = message.getBoolean("checked", false);
|
||||
info.enabled = message.getBoolean("enabled", true);
|
||||
info.visible = message.getBoolean("visible", true);
|
||||
info.checkable = message.getBoolean("checkable", false);
|
||||
final int parent = message.getInt("parent", 0);
|
||||
info.parent = parent <= 0 ? parent : parent + ADDON_MENU_OFFSET;
|
||||
addAddonMenuItem(info);
|
||||
break;
|
||||
|
||||
case "Menu:Remove":
|
||||
removeAddonMenuItem(message.getInt("id") + ADDON_MENU_OFFSET);
|
||||
break;
|
||||
|
||||
case "LightweightTheme:Update":
|
||||
mDynamicToolbar.setVisible(true, VisibilityTransition.ANIMATE);
|
||||
break;
|
||||
|
||||
case "Search:Keyword":
|
||||
storeSearchQuery(message.getString("query"));
|
||||
recordSearch(GeckoSharedPrefs.forProfile(this), message.getString("identifier"),
|
||||
TelemetryContract.Method.ACTIONBAR);
|
||||
break;
|
||||
|
||||
case "Prompt:ShowTop":
|
||||
// Bring this activity to front so the prompt is visible..
|
||||
Intent bringToFrontIntent = new Intent();
|
||||
|
@ -1715,21 +1810,32 @@ public class BrowserApp extends GeckoApp
|
|||
bringToFrontIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
startActivity(bringToFrontIntent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final NativeJSObject message,
|
||||
final EventCallback callback) {
|
||||
switch (event) {
|
||||
case "Tab:Added":
|
||||
if (message.getBoolean("cancelEditMode")) {
|
||||
// Set the target tab to null so it does not get selected (on editing
|
||||
// mode exit) in lieu of the tab that we're going to open and select.
|
||||
mTargetTabForEditingMode = null;
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
break;
|
||||
|
||||
case "Video:Play":
|
||||
if (SwitchBoard.isInExperiment(this, Experiments.HLS_VIDEO_PLAYBACK)) {
|
||||
mVideoPlayer.start(Uri.parse(message.getString("uri")));
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW,
|
||||
TelemetryContract.Method.CONTENT, "playhls");
|
||||
}
|
||||
break;
|
||||
|
||||
case "CharEncoding:Data":
|
||||
final NativeJSObject[] charsets = message.getObjectArray("charsets");
|
||||
final GeckoBundle[] charsets = message.getBundleArray("charsets");
|
||||
final int selected = message.getInt("selected");
|
||||
|
||||
final String[] titleArray = new String[charsets.length];
|
||||
final String[] codeArray = new String[charsets.length];
|
||||
for (int i = 0; i < charsets.length; i++) {
|
||||
final NativeJSObject charset = charsets[i];
|
||||
final GeckoBundle charset = charsets[i];
|
||||
titleArray[i] = charset.getString("title");
|
||||
codeArray[i] = charset.getString("code");
|
||||
}
|
||||
|
@ -1750,26 +1856,15 @@ public class BrowserApp extends GeckoApp
|
|||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialogBuilder.show();
|
||||
}
|
||||
});
|
||||
dialogBuilder.show();
|
||||
break;
|
||||
|
||||
case "CharEncoding:State":
|
||||
final boolean visible = message.getString("visible").equals("true");
|
||||
final boolean visible = "true".equals(message.getString("visible"));
|
||||
GeckoPreferences.setCharEncodingState(visible);
|
||||
final Menu menu = mMenu;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (menu != null) {
|
||||
menu.findItem(R.id.char_encoding).setVisible(visible);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (mMenu != null) {
|
||||
mMenu.findItem(R.id.char_encoding).setVisible(visible);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Experiments:GetActive":
|
||||
|
@ -1779,7 +1874,8 @@ public class BrowserApp extends GeckoApp
|
|||
break;
|
||||
|
||||
case "Experiments:SetOverride":
|
||||
Experiments.setOverride(getContext(), message.getString("name"), message.getBoolean("isEnabled"));
|
||||
Experiments.setOverride(getContext(), message.getString("name"),
|
||||
message.getBoolean("isEnabled"));
|
||||
break;
|
||||
|
||||
case "Experiments:ClearOverride":
|
||||
|
@ -1792,52 +1888,25 @@ public class BrowserApp extends GeckoApp
|
|||
break;
|
||||
|
||||
case "Feedback:MaybeLater":
|
||||
resetFeedbackLaunchCount();
|
||||
break;
|
||||
|
||||
case "Menu:Add":
|
||||
final MenuItemInfo info = new MenuItemInfo();
|
||||
info.label = message.getString("name");
|
||||
info.id = message.getInt("id") + ADDON_MENU_OFFSET;
|
||||
info.checked = message.optBoolean("checked", false);
|
||||
info.enabled = message.optBoolean("enabled", true);
|
||||
info.visible = message.optBoolean("visible", true);
|
||||
info.checkable = message.optBoolean("checkable", false);
|
||||
final int parent = message.optInt("parent", 0);
|
||||
info.parent = parent <= 0 ? parent : parent + ADDON_MENU_OFFSET;
|
||||
final MenuItemInfo menuItemInfo = info;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addAddonMenuItem(menuItemInfo);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "Menu:Remove":
|
||||
final int id = message.getInt("id") + ADDON_MENU_OFFSET;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeAddonMenuItem(id);
|
||||
}
|
||||
});
|
||||
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
|
||||
settings.edit().putInt(getPackageName() + ".feedback_launch_count", 0).apply();
|
||||
break;
|
||||
|
||||
case "Sanitize:ClearHistory":
|
||||
handleClearHistory(message.optBoolean("clearSearchHistory", false));
|
||||
callback.sendSuccess(true);
|
||||
BrowserDB.from(getProfile()).clearHistory(
|
||||
getContentResolver(), message.getBoolean("clearSearchHistory", false));
|
||||
callback.sendSuccess(null);
|
||||
break;
|
||||
|
||||
case "Sanitize:ClearSyncedTabs":
|
||||
handleClearSyncedTabs();
|
||||
callback.sendSuccess(true);
|
||||
FennecTabsRepository.deleteNonLocalClientsAndTabs(getContext());
|
||||
callback.sendSuccess(null);
|
||||
break;
|
||||
|
||||
case "Settings:Show":
|
||||
final String resource =
|
||||
message.optString(GeckoPreferences.INTENT_EXTRA_RESOURCES, null);
|
||||
final Intent settingsIntent = new Intent(this, GeckoPreferences.class);
|
||||
final String resource = message.getString(GeckoPreferences.INTENT_EXTRA_RESOURCES);
|
||||
|
||||
GeckoPreferences.setResourceToOpen(settingsIntent, resource);
|
||||
startActivityForResult(settingsIntent, ACTIVITY_REQUEST_PREFERENCES);
|
||||
|
||||
|
@ -1851,30 +1920,58 @@ public class BrowserApp extends GeckoApp
|
|||
case "Telemetry:Gather":
|
||||
final BrowserDB db = BrowserDB.from(getProfile());
|
||||
final ContentResolver cr = getContentResolver();
|
||||
|
||||
Telemetry.addToHistogram("PLACES_PAGES_COUNT", db.getCount(cr, "history"));
|
||||
Telemetry.addToHistogram("FENNEC_BOOKMARKS_COUNT", db.getCount(cr, "bookmarks"));
|
||||
Telemetry.addToHistogram("BROWSER_IS_USER_DEFAULT", (isDefaultBrowser(Intent.ACTION_VIEW) ? 1 : 0));
|
||||
Telemetry.addToHistogram("FENNEC_CUSTOM_HOMEPAGE", (TextUtils.isEmpty(getHomepage()) ? 0 : 1));
|
||||
Telemetry.addToHistogram("BROWSER_IS_USER_DEFAULT",
|
||||
(isDefaultBrowser(Intent.ACTION_VIEW) ? 1 : 0));
|
||||
Telemetry.addToHistogram("FENNEC_CUSTOM_HOMEPAGE",
|
||||
(TextUtils.isEmpty(getHomepage()) ? 0 : 1));
|
||||
|
||||
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(getContext());
|
||||
final boolean hasCustomHomepanels =
|
||||
prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY) || prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY_OLD);
|
||||
prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY) ||
|
||||
prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY_OLD);
|
||||
|
||||
Telemetry.addToHistogram("FENNEC_HOMEPANELS_CUSTOM", hasCustomHomepanels ? 1 : 0);
|
||||
|
||||
Telemetry.addToHistogram("FENNEC_READER_VIEW_CACHE_SIZE",
|
||||
SavedReaderViewHelper.getSavedReaderViewHelper(getContext()).getDiskSpacedUsedKB());
|
||||
SavedReaderViewHelper.getSavedReaderViewHelper(getContext())
|
||||
.getDiskSpacedUsedKB());
|
||||
|
||||
if (Versions.feature16Plus) {
|
||||
Telemetry.addToHistogram("BROWSER_IS_ASSIST_DEFAULT", (isDefaultBrowser(Intent.ACTION_ASSIST) ? 1 : 0));
|
||||
Telemetry.addToHistogram("BROWSER_IS_ASSIST_DEFAULT",
|
||||
(isDefaultBrowser(Intent.ACTION_ASSIST) ? 1 : 0));
|
||||
}
|
||||
break;
|
||||
|
||||
case "Updater:Launch":
|
||||
handleUpdaterLaunch();
|
||||
/**
|
||||
* Launch UI that lets the user update Firefox.
|
||||
*
|
||||
* This depends on the current channel: Release and Beta both direct to
|
||||
* the Google Play Store. If updating is enabled, Aurora, Nightly, and
|
||||
* custom builds open about:, which provides an update interface.
|
||||
*
|
||||
* If updating is not enabled, this simply logs an error.
|
||||
*/
|
||||
if (AppConstants.RELEASE_OR_BETA) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse("market://details?id=" + getPackageName()));
|
||||
startActivity(intent);
|
||||
break;
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_UPDATER) {
|
||||
Tabs.getInstance().loadUrlInTab(AboutPages.UPDATER);
|
||||
break;
|
||||
}
|
||||
|
||||
Log.w(LOGTAG, "No candidate updater found; ignoring launch request.");
|
||||
break;
|
||||
|
||||
case "Download:AndroidDownloadManager":
|
||||
// Downloading via Android's download manager
|
||||
|
||||
final String uri = message.getString("uri");
|
||||
final String filename = message.getString("filename");
|
||||
final String mimeType = message.getString("mimeType");
|
||||
|
@ -1883,54 +1980,49 @@ public class BrowserApp extends GeckoApp
|
|||
request.setMimeType(mimeType);
|
||||
|
||||
try {
|
||||
request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, filename);
|
||||
request.setDestinationInExternalFilesDir(
|
||||
this, Environment.DIRECTORY_DOWNLOADS, filename);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(LOGTAG, "Cannot create download directory");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
request.allowScanningByMediaScanner();
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.setNotificationVisibility(
|
||||
DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.addRequestHeader("User-Agent", HardwareUtils.isTablet() ?
|
||||
AppConstants.USER_AGENT_FENNEC_TABLET :
|
||||
AppConstants.USER_AGENT_FENNEC_MOBILE);
|
||||
|
||||
try {
|
||||
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
DownloadManager manager = (DownloadManager)
|
||||
getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
manager.enqueue(request);
|
||||
|
||||
Log.d(LOGTAG, "Enqueued download (Download Manager)");
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(LOGTAG, "Download failed: " + e);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Website:Metadata":
|
||||
final NativeJSObject metadata = message.getObject("metadata");
|
||||
final String location = message.getString("location");
|
||||
final boolean hasImage = message.getBoolean("hasImage");
|
||||
final String metadata = message.getString("metadata");
|
||||
|
||||
final boolean hasImage = !TextUtils.isEmpty(metadata.optString("image_url", null));
|
||||
final String metadataJSON = metadata.toString();
|
||||
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ContentProviderClient contentProviderClient = getContentResolver()
|
||||
.acquireContentProviderClient(BrowserContract.PageMetadata.CONTENT_URI);
|
||||
if (contentProviderClient == null) {
|
||||
Log.w(LOGTAG, "Failed to obtain content provider client for: " + BrowserContract.PageMetadata.CONTENT_URI);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
GlobalPageMetadata.getInstance().add(
|
||||
BrowserDB.from(getProfile()),
|
||||
contentProviderClient,
|
||||
location, hasImage, metadataJSON);
|
||||
} finally {
|
||||
contentProviderClient.release();
|
||||
}
|
||||
}
|
||||
});
|
||||
final ContentProviderClient contentProviderClient = getContentResolver()
|
||||
.acquireContentProviderClient(BrowserContract.PageMetadata.CONTENT_URI);
|
||||
if (contentProviderClient == null) {
|
||||
Log.w(LOGTAG, "Failed to obtain content provider client for: " +
|
||||
BrowserContract.PageMetadata.CONTENT_URI);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
GlobalPageMetadata.getInstance().add(
|
||||
BrowserDB.from(getProfile()),
|
||||
contentProviderClient,
|
||||
location, hasImage, metadata);
|
||||
} finally {
|
||||
contentProviderClient.release();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
@ -1994,164 +2086,6 @@ public class BrowserApp extends GeckoApp
|
|||
return (TextUtils.equals(packageName, getPackageName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
try {
|
||||
switch (event) {
|
||||
case "Menu:Open":
|
||||
if (mBrowserToolbar.isEditing()) {
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
|
||||
openOptionsMenu();
|
||||
break;
|
||||
|
||||
case "Menu:Update":
|
||||
final int id = message.getInt("id") + ADDON_MENU_OFFSET;
|
||||
final JSONObject options = message.getJSONObject("options");
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateAddonMenuItem(id, options);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "Gecko:DelayedStartup":
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Force tabs panel inflation once the initial
|
||||
// pageload is finished.
|
||||
ensureTabsPanelExists();
|
||||
if (AppConstants.NIGHTLY_BUILD && mZoomedView == null) {
|
||||
ViewStub stub = (ViewStub) findViewById(R.id.zoomed_view_stub);
|
||||
mZoomedView = (ZoomedView) stub.inflate();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (AppConstants.MOZ_MEDIA_PLAYER) {
|
||||
// Check if the fragment is already added. This should never be true here, but this is
|
||||
// a nice safety check.
|
||||
// If casting is disabled, these classes aren't built. We use reflection to initialize them.
|
||||
final Class<?> mediaManagerClass = getMediaPlayerManager();
|
||||
|
||||
if (mediaManagerClass != null) {
|
||||
try {
|
||||
final String tag = "";
|
||||
mediaManagerClass.getDeclaredField("MEDIA_PLAYER_TAG").get(tag);
|
||||
Log.i(LOGTAG, "Found tag " + tag);
|
||||
final Fragment frag = getSupportFragmentManager().findFragmentByTag(tag);
|
||||
if (frag == null) {
|
||||
final Method getInstance = mediaManagerClass.getMethod("getInstance", (Class[]) null);
|
||||
final Fragment mpm = (Fragment) getInstance.invoke(null);
|
||||
getSupportFragmentManager().beginTransaction().disallowAddToBackStack().add(mpm, tag).commit();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.e(LOGTAG, "Error initializing media manager", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED && Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
|
||||
// Start (this acts as ping if started already) the stumbler lib; if the stumbler has queued data it will upload it.
|
||||
// Stumbler operates on its own thread, and startup impact is further minimized by delaying work (such as upload) a few seconds.
|
||||
// Avoid any potential startup CPU/thread contention by delaying the pref broadcast.
|
||||
final long oneSecondInMillis = 1000;
|
||||
ThreadUtils.getBackgroundHandler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GeckoPreferences.broadcastStumblerPref(BrowserApp.this);
|
||||
}
|
||||
}, oneSecondInMillis);
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE) {
|
||||
// TODO: Better scheduling of sync action (Bug 1257492)
|
||||
DownloadContentService.startSync(this);
|
||||
|
||||
DownloadContentService.startVerification(this);
|
||||
}
|
||||
|
||||
FeedService.setup(this);
|
||||
|
||||
super.handleMessage(event, message);
|
||||
break;
|
||||
|
||||
case "Gecko:Ready":
|
||||
// Handle this message in GeckoApp, but also enable the Settings
|
||||
// menuitem, which is specific to BrowserApp.
|
||||
super.handleMessage(event, message);
|
||||
final Menu menu = mMenu;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (menu != null) {
|
||||
menu.findItem(R.id.settings).setEnabled(true);
|
||||
menu.findItem(R.id.help).setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Display notification for Mozilla data reporting, if data should be collected.
|
||||
if (AppConstants.MOZ_DATA_REPORTING && Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
|
||||
DataReportingNotification.checkAndNotifyPolicy(GeckoAppShell.getContext());
|
||||
}
|
||||
break;
|
||||
|
||||
case "Search:Keyword":
|
||||
storeSearchQuery(message.getString("query"));
|
||||
recordSearch(GeckoSharedPrefs.forProfile(this), message.getString("identifier"),
|
||||
TelemetryContract.Method.ACTIONBAR);
|
||||
break;
|
||||
|
||||
case "LightweightTheme:Update":
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDynamicToolbar.setVisible(true, VisibilityTransition.ANIMATE);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case "Video:Play":
|
||||
if (SwitchBoard.isInExperiment(this, Experiments.HLS_VIDEO_PLAYBACK)) {
|
||||
final String uri = message.getString("uri");
|
||||
final String uuid = message.getString("uuid");
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mVideoPlayer.start(Uri.parse(uri));
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.CONTENT, "playhls");
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case "Tab:Added":
|
||||
if (message.getBoolean("cancelEditMode")) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Set the target tab to null so it does not get selected (on editing
|
||||
// mode exit) in lieu of the tab that we're going to open and select.
|
||||
mTargetTabForEditingMode = null;
|
||||
mBrowserToolbar.cancelEdit();
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
super.handleMessage(event, message);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTab() {
|
||||
Tabs.getInstance().addTab();
|
||||
|
@ -3248,16 +3182,16 @@ public class BrowserApp extends GeckoApp
|
|||
mMenu.removeItem(id);
|
||||
}
|
||||
|
||||
private void updateAddonMenuItem(int id, JSONObject options) {
|
||||
private void updateAddonMenuItem(int id, final GeckoBundle options) {
|
||||
// Set attribute for the menu item in cache, if available
|
||||
if (mAddonMenuItemsCache != null && !mAddonMenuItemsCache.isEmpty()) {
|
||||
for (MenuItemInfo item : mAddonMenuItemsCache) {
|
||||
if (item.id == id) {
|
||||
item.label = options.optString("name", item.label);
|
||||
item.checkable = options.optBoolean("checkable", item.checkable);
|
||||
item.checked = options.optBoolean("checked", item.checked);
|
||||
item.enabled = options.optBoolean("enabled", item.enabled);
|
||||
item.visible = options.optBoolean("visible", item.visible);
|
||||
item.label = options.getString("name", item.label);
|
||||
item.checkable = options.getBoolean("checkable", item.checkable);
|
||||
item.checked = options.getBoolean("checked", item.checked);
|
||||
item.enabled = options.getBoolean("enabled", item.enabled);
|
||||
item.visible = options.getBoolean("visible", item.visible);
|
||||
item.added = (mMenu != null);
|
||||
break;
|
||||
}
|
||||
|
@ -3270,11 +3204,11 @@ public class BrowserApp extends GeckoApp
|
|||
|
||||
final MenuItem menuItem = mMenu.findItem(id);
|
||||
if (menuItem != null) {
|
||||
menuItem.setTitle(options.optString("name", menuItem.getTitle().toString()));
|
||||
menuItem.setCheckable(options.optBoolean("checkable", menuItem.isCheckable()));
|
||||
menuItem.setChecked(options.optBoolean("checked", menuItem.isChecked()));
|
||||
menuItem.setEnabled(options.optBoolean("enabled", menuItem.isEnabled()));
|
||||
menuItem.setVisible(options.optBoolean("visible", menuItem.isVisible()));
|
||||
menuItem.setTitle(options.getString("name", menuItem.getTitle().toString()));
|
||||
menuItem.setCheckable(options.getBoolean("checkable", menuItem.isCheckable()));
|
||||
menuItem.setChecked(options.getBoolean("checked", menuItem.isChecked()));
|
||||
menuItem.setEnabled(options.getBoolean("enabled", menuItem.isEnabled()));
|
||||
menuItem.setVisible(options.getBoolean("visible", menuItem.isVisible()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4029,11 +3963,6 @@ public class BrowserApp extends GeckoApp
|
|||
});
|
||||
}
|
||||
|
||||
private void resetFeedbackLaunchCount() {
|
||||
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
|
||||
settings.edit().putInt(getPackageName() + ".feedback_launch_count", 0).apply();
|
||||
}
|
||||
|
||||
// HomePager.OnUrlOpenListener
|
||||
@Override
|
||||
public void onUrlOpen(String url, EnumSet<OnUrlOpenListener.Flags> flags) {
|
||||
|
@ -4147,34 +4076,6 @@ public class BrowserApp extends GeckoApp
|
|||
return mReadingListHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch UI that lets the user update Firefox.
|
||||
*
|
||||
* This depends on the current channel: Release and Beta both direct to the
|
||||
* Google Play Store. If updating is enabled, Aurora, Nightly, and custom
|
||||
* builds open about:, which provides an update interface.
|
||||
*
|
||||
* If updating is not enabled, this simply logs an error.
|
||||
*
|
||||
* @return true if update UI was launched.
|
||||
*/
|
||||
protected boolean handleUpdaterLaunch() {
|
||||
if (AppConstants.RELEASE_OR_BETA) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse("market://details?id=" + getPackageName()));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_UPDATER) {
|
||||
Tabs.getInstance().loadUrlInTab(AboutPages.UPDATER);
|
||||
return true;
|
||||
}
|
||||
|
||||
Log.w(LOGTAG, "No candidate updater found; ignoring launch request.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Implementing ActionModeCompat.Presenter */
|
||||
@Override
|
||||
public void startActionModeCompat(final ActionModeCompat.Callback callback) {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче