Grammalecte  Changes On Branch 04f81fab7f8ff4e4

Changes In Branch mailext Through [04f81fab7f] Excluding Merge-Ins

This is equivalent to a diff from 3d30d02ecf to 04f81fab7f

2020-07-04
10:23
[fr] conf: tandis que, + phonet_simil: tandis / tendis / tendit check-in: ee8c478284 user: olr tags: trunk, fr
2020-07-02
12:32
[tb] remove deprecated files check-in: 124d6884b2 user: olr tags: tb, mailext
12:31
[tb] remove deprecated files check-in: 04f81fab7f user: olr tags: tb, mailext
12:23
[tb] MailExtension for Thunderbird 78 check-in: 4c21586958 user: olr tags: tb, mailext
09:04
[fr] faux positif et ajustements check-in: 3d30d02ecf user: olr tags: trunk, fr
2020-07-01
06:17
[fr] ajustements check-in: f4c70b8022 user: olr tags: trunk, fr

Deleted gc_lang/fr/mailext/content/about.css version [0c03b7bf9e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46














































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* CSS */

.descr {
	font-size: 18px;
	font-weight: bold;
	text-align: center;
}

.stdlabel {
	font-size: 16px;
	text-align: center;
}

#website {
	font-size: 16px;
	font-weight: bold;
	color: hsl(210, 50%, 50%);
	text-align: center;
	cursor: pointer;
}

#contrib {
	font-size: 16px;
	text-align: center;
	color: hsl(210, 50%, 50%);
	cursor: pointer;
}


/*
    TB Next: fix dialogheaders
*/
dialogheader {
  -moz-binding: url("chrome://messenger/content/generalBindings.xml#dialogheader");
  margin: 0 5px 5px;
  border: 1px solid ThreeDDarkShadow;
  padding: 5px 8px;
  background-color: Highlight;
  color: HighlightText;
}

.dialogheader-title {
  margin: 0 !important;
  font-size: larger;
  font-weight: bold;
}

Deleted gc_lang/fr/mailext/content/about.js version [94f44e1159].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35



































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// JavaScript

const Cc = Components.classes;
const Ci = Components.interfaces;
//const Cu = Components.utils;


function openInBrowserURL (sURL) {
    // method found in S3.Google.Translator
    try {
        openURL(sURL);
        // Works in overlay.js, but not here… Seems there is no documentation available about this feature on Mozilla.org
    }
    catch (e) {
        console.error(e);
        //Cu.reportError(e);
    }
}

function openInTabURL (sURL) {
    // method found in S3.Google.Translator
    try {
        let xWM = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
        let xWin = xWM.getMostRecentWindow("mail:3pane");
        let xTabmail = xWin.document.getElementById('tabmail');
        xWin.focus();
        if (xTabmail) {
            xTabmail.openTab('contentTab', { contentPage: sURL });
        }
    }
    catch (e) {
        console.error(e);
        //Cu.reportError(e);
    }
}

Deleted gc_lang/fr/mailext/content/about.xul version [6f2fa2e063].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38






































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://grammarchecker/content/about.css" type="text/css"?>

<!DOCTYPE dialog SYSTEM "chrome://grammarchecker/locale/about.dtd">

<dialog
  id="grammalecte-about-window"
  title="&windowtitle;"
  orient="vertical"
  buttons="accept"
  width="300"
  onload="document.getElementById('grammalecte-about-window').centerWindowOnScreen();"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <!-- Other elements go here -->
  <description  style="text-align: center;">
    <image src="chrome://grammarchecker/skin/logo120_text.png" />
  </description>
  <label class="descr">&description1;</label>
  <label class="descr">&description2;</label>
  <label class="stdlabel" value="&version; ${version}" />
  <label class="stdlabel" value="&license; GPL 3" />
  <label id="website" value="Site web" onclick="openInTabURL('https://grammalecte.net/?from=grammalecte-tb');" />

  <separator class="groove" orient="horizontal" style="margin: 10px;"/>

  <label class="stdlabel" value="&thanks;" />
  <image src="chrome://grammarchecker/skin/LaMouette_small.png" style="cursor: pointer;"
    onclick="openInTabURL('http://lamouette.org/?from=grammalecte-tb');" />
  <label class="stdlabel" value="&amp;" />
  <image src="chrome://grammarchecker/skin/Algoo_logo.png" style="cursor: pointer;"
    onclick="openInTabURL('https://www.algoo.fr/?from=grammalecte-tb');" />
  <label id="contrib" value="&contrib;"
    onclick="openInTabURL('https://grammalecte.net/#thanks');" />

  <script type="application/javascript" src="about.js"/>
</dialog>

Deleted gc_lang/fr/mailext/content/conjugueur.css version [c5ad386744].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* CSS */

#verb {
    width: 200px;
}

#verb_title {
    font-size: 24px;
    font-weight: bold;
    text-align: center;
    color: hsl(210, 50%, 50%);
}

#info {
    font-size: 16px;
    text-align: center;
    vertical-align: bottom;
}


.groupbox {
    margin-left: 5px;
    margin-bottom: 5px;
    width: 275px;
    border: 1px solid hsl(0, 0%, 90%);
    border-radius: 5px;
}

#smallnote {
    font-size: 10px;
    width: 250px;
}

.sub_header {
    color: hsl(0, 50%, 50%);
    font-size: 16px;
    font-weight: bold;
    border-bottom: 1px solid hsl(0, 0%, 80%);
}

label.temps {
    color: hsl(210, 50%, 50%);
    font-size: 13px;
    font-weight: bold;
}
label.cj {
    font-size: 11px;
}

Deleted gc_lang/fr/mailext/content/conjugueur.js version [de46feffb0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218


























































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// JavaScript

//const Cu = Components.utils;
//const { require } = Cu.import("resource://gre/modules/commonjs/toolkit/require.js", {});
//const conj = require("resource://grammalecte/fr/conj.js");


let oConj = {
    init: function () {
        console.log("Init conjugueur");
        try {
            // button
            document.getElementById('conjugate').addEventListener("click", (xEvent) => {
                this.getVerbAndConjugate();
            });
            // text field
            document.getElementById('verb').addEventListener("change", (xEvent) => {
                this.getVerbAndConjugate();
            });
            // options
            document.getElementById('oneg').addEventListener("click", (xEvent) => {
                this._displayResults();
            });
            document.getElementById('opro').addEventListener("click", (xEvent) => {
                this._displayResults();
            });
            document.getElementById('oint').addEventListener("click", (xEvent) => {
                this._displayResults();
            });
            document.getElementById('ofem').addEventListener("click", (xEvent) => {
                this._displayResults();
            });
            document.getElementById('otco').addEventListener("click", (xEvent) => {
                this._displayResults();
            });
        }
        catch (e) {
            console.error(e);
        }
        this.conjugate("être");
    },

    oVerb: null,

    getVerbAndConjugate: function () {
        this.conjugate(document.getElementById('verb').value);
    },

    conjugate: function (sVerb) {
        try {
            document.getElementById('oneg').checked = false;
            document.getElementById('opro').checked = false;
            document.getElementById('oint').checked = false;
            document.getElementById('otco').checked = false;
            document.getElementById('ofem').checked = false;
            document.getElementById('smallnote').hidden = true;

            // request analyzing
            sVerb = sVerb.trim().toLowerCase().replace(/’/g, "'").replace(/  +/g, " ");
            if (sVerb) {
                if (sVerb.startsWith("ne pas ")) {
                    document.getElementById('oneg').checked = true;
                    sVerb = sVerb.slice(7);
                }
                if (sVerb.startsWith("se ")) {
                    document.getElementById('opro').checked = true;
                    sVerb = sVerb.slice(3);
                } else if (sVerb.startsWith("s'")) {
                    document.getElementById('opro').checked = true;
                    sVerb = sVerb.slice(2);
                }
                if (sVerb.endsWith("?")) {
                    document.getElementById('oint').checked = true;
                    sVerb = sVerb.slice(0,-1).trim();
                }

                if (!conj.isVerb(sVerb)) {
                    document.getElementById('verb').style = "color: #BB4411;";
                } else {
                    document.getElementById('verb_title').textContent = sVerb;
                    document.getElementById('verb').style = "color: #999999;";
                    document.getElementById('verb').value = "";
                    this.oVerb = new Verb(sVerb);
                    document.getElementById('info').textContent = this.oVerb.sInfo;
                    document.getElementById('opro').label = this.oVerb.sProLabel;
                    if (this.oVerb.bUncomplete) {
                        document.getElementById('opro').checked = false;
                        document.getElementById('opro').disabled = true;
                        document.getElementById('opro').style = "color: #CCC;";
                        document.getElementById('otco').checked = false;
                        document.getElementById('otco').disabled = true;
                        document.getElementById('otco').style = "color: #CCC;";
                        document.getElementById('smallnote').hidden = false;
                    } else {
                        document.getElementById('otco').disabled = false;
                        document.getElementById('otco').style = "color: #000;";
                        if (this.oVerb.nPronominable == 0) {
                            document.getElementById('opro').checked = false;
                            document.getElementById('opro').disabled = false;
                            document.getElementById('opro').style = "color: #000;";
                        } else if (this.oVerb.nPronominable == 1) {
                            document.getElementById('opro').checked = true;
                            document.getElementById('opro').disabled = true;
                            document.getElementById('opro').style = "color: #CCC;";
                        } else { // -1 or 1 or error
                            document.getElementById('opro').checked = false;
                            document.getElementById('opro').disabled = true;
                            document.getElementById('opro').style = "color: #CCC;";
                        }
                        document.getElementById('smallnote').hidden = true;
                    }
                    this._displayResults();
                }
            }
        }
        catch (e) {
            console.error(e);
        }
    },

    _displayResults: function () {
        if (this.oVerb === null) {
            return;
        }
        try {
            let bPro = document.getElementById('opro').checked;
            let bNeg = document.getElementById('oneg').checked;
            let bTCo = document.getElementById('otco').checked;
            let bInt = document.getElementById('oint').checked;
            let bFem = document.getElementById('ofem').checked;
            let oConjTable = this.oVerb.createConjTable(bPro, bNeg, bTCo, bInt, bFem);
            document.getElementById('verb').Text = "";
            // infinitif
            document.getElementById('infi').textContent = oConjTable["infi"] || " "; // something or nbsp
            // participe présent
            document.getElementById('ppre').textContent = oConjTable["ppre"] || " ";
            // participes passés
            document.getElementById('ppas1').textContent = oConjTable["ppas1"] || " ";
            document.getElementById('ppas2').textContent = oConjTable["ppas2"] || " ";
            document.getElementById('ppas3').textContent = oConjTable["ppas3"] || " ";
            document.getElementById('ppas4').textContent = oConjTable["ppas4"] || " ";
            // impératif
            document.getElementById('impe_temps').textContent = oConjTable["t_impe"] || " ";
            document.getElementById('impe1').textContent = oConjTable["impe1"] || " ";
            document.getElementById('impe2').textContent = oConjTable["impe2"] || " ";
            document.getElementById('impe3').textContent = oConjTable["impe3"] || " ";
            // présent
            document.getElementById('ipre_temps').textContent = oConjTable["t_ipre"] || " ";
            document.getElementById('ipre1').textContent = oConjTable["ipre1"] || " ";
            document.getElementById('ipre2').textContent = oConjTable["ipre2"] || " ";
            document.getElementById('ipre3').textContent = oConjTable["ipre3"] || " ";
            document.getElementById('ipre4').textContent = oConjTable["ipre4"] || " ";
            document.getElementById('ipre5').textContent = oConjTable["ipre5"] || " ";
            document.getElementById('ipre6').textContent = oConjTable["ipre6"] || " ";
            // imparfait
            document.getElementById('iimp_temps').textContent = oConjTable["t_iimp"] || " ";
            document.getElementById('iimp1').textContent = oConjTable["iimp1"] || " ";
            document.getElementById('iimp2').textContent = oConjTable["iimp2"] || " ";
            document.getElementById('iimp3').textContent = oConjTable["iimp3"] || " ";
            document.getElementById('iimp4').textContent = oConjTable["iimp4"] || " ";
            document.getElementById('iimp5').textContent = oConjTable["iimp5"] || " ";
            document.getElementById('iimp6').textContent = oConjTable["iimp6"] || " ";
            // passé simple
            document.getElementById('ipsi_temps').textContent = oConjTable["t_ipsi"] || " ";
            document.getElementById('ipsi1').textContent = oConjTable["ipsi1"] || " ";
            document.getElementById('ipsi2').textContent = oConjTable["ipsi2"] || " ";
            document.getElementById('ipsi3').textContent = oConjTable["ipsi3"] || " ";
            document.getElementById('ipsi4').textContent = oConjTable["ipsi4"] || " ";
            document.getElementById('ipsi5').textContent = oConjTable["ipsi5"] || " ";
            document.getElementById('ipsi6').textContent = oConjTable["ipsi6"] || " ";
            // futur
            document.getElementById('ifut_temps').textContent = oConjTable["t_ifut"] || " ";
            document.getElementById('ifut1').textContent = oConjTable["ifut1"] || " ";
            document.getElementById('ifut2').textContent = oConjTable["ifut2"] || " ";
            document.getElementById('ifut3').textContent = oConjTable["ifut3"] || " ";
            document.getElementById('ifut4').textContent = oConjTable["ifut4"] || " ";
            document.getElementById('ifut5').textContent = oConjTable["ifut5"] || " ";
            document.getElementById('ifut6').textContent = oConjTable["ifut6"] || " ";
            // Conditionnel
            document.getElementById('conda_temps').textContent = oConjTable["t_conda"] || " ";
            document.getElementById('conda1').textContent = oConjTable["conda1"] || " ";
            document.getElementById('conda2').textContent = oConjTable["conda2"] || " ";
            document.getElementById('conda3').textContent = oConjTable["conda3"] || " ";
            document.getElementById('conda4').textContent = oConjTable["conda4"] || " ";
            document.getElementById('conda5').textContent = oConjTable["conda5"] || " ";
            document.getElementById('conda6').textContent = oConjTable["conda6"] || " ";
            document.getElementById('condb_temps').textContent = oConjTable["t_condb"] || " ";
            document.getElementById('condb1').textContent = oConjTable["condb1"] || " ";
            document.getElementById('condb2').textContent = oConjTable["condb2"] || " ";
            document.getElementById('condb3').textContent = oConjTable["condb3"] || " ";
            document.getElementById('condb4').textContent = oConjTable["condb4"] || " ";
            document.getElementById('condb5').textContent = oConjTable["condb5"] || " ";
            document.getElementById('condb6').textContent = oConjTable["condb6"] || " ";
            // subjonctif présent
            document.getElementById('spre_temps').textContent = oConjTable["t_spre"] || " ";
            document.getElementById('spre1').textContent = oConjTable["spre1"] || " ";
            document.getElementById('spre2').textContent = oConjTable["spre2"] || " ";
            document.getElementById('spre3').textContent = oConjTable["spre3"] || " ";
            document.getElementById('spre4').textContent = oConjTable["spre4"] || " ";
            document.getElementById('spre5').textContent = oConjTable["spre5"] || " ";
            document.getElementById('spre6').textContent = oConjTable["spre6"] || " ";
            // subjonctif imparfait
            document.getElementById('simp_temps').textContent = oConjTable["t_simp"] || " ";
            document.getElementById('simp1').textContent = oConjTable["simp1"] || " ";
            document.getElementById('simp2').textContent = oConjTable["simp2"] || " ";
            document.getElementById('simp3').textContent = oConjTable["simp3"] || " ";
            document.getElementById('simp4').textContent = oConjTable["simp4"] || " ";
            document.getElementById('simp5').textContent = oConjTable["simp5"] || " ";
            document.getElementById('simp6').textContent = oConjTable["simp6"] || " ";
        }
        catch (e) {
            console.error(e);
        }
    }
};

conj.init(helpers.loadFile("resource://grammalecte/fr/conj_data.json"));
oConj.init();

Deleted gc_lang/fr/mailext/content/conjugueur.xul version [7d69e0ed2b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162


































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://grammarchecker/content/conjugueur.css" type="text/css"?>


<dialog
  id="grammalecte-conjugueur-window"
  title="Grammalecte · Conjugueur…"
  orient="vertical"
  width="580"
  buttons="extra1"
  buttonlabelextra1="Conjuguer"
  ondialogextra1="oConj.getVerbAndConjugate();"
  defaultButton="extra1"
  onload="document.getElementById('grammalecte-conjugueur-window').centerWindowOnScreen();"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">


  <!-- Other elements go here -->
  <box>
    <spacer flex="1"/>
    <image src="chrome://grammarchecker/skin/grammarcheck.png" />
    <textbox id="verb" value="" />
    <button id="conjugate" label="Conjuguer" />
    <spacer flex="1"/>
  </box>

  <box>
    <spacer flex="1"/>
    <checkbox id="oneg" label="Négation" />
    <checkbox id="opro" label="Pronominal" />
    <checkbox id="ofem" label="Féminin" />
    <checkbox id="oint" label="Interrogatif" />
    <checkbox id="otco" label="Temps composés" />
    <spacer flex="1"/>
  </box>

  <box>
    <spacer flex="1"/>
    <box orient="vertical">
      <label id="verb_title">.</label>
      <label id="info">.</label>
    </box>
    <spacer flex="1"/>
  </box>

  <columns>
    <column>
      <groupbox class="groupbox" id="infinitif">
        <label class="sub_header">Infinitif</label>
        <label id="infi" class="cj">.</label>
      </groupbox>

      <groupbox class="groupbox" id="imperatif">
        <label class="sub_header">Impératif</label>
        <label id="impe_temps" class="temps">Présent</label>
        <label id="impe1" class="cj">.</label>
        <label id="impe2" class="cj">.</label>
        <label id="impe3" class="cj">.</label>
      </groupbox>
    </column>

    <column>
      <groupbox class="groupbox" id="partpre">
        <label class="sub_header">Participe présent</label>
        <label id="ppre" class="cj">.</label>
      </groupbox>

      <groupbox class="groupbox" id="partpas">
        <label class="sub_header">Participes passés</label>
        <label id="ppas1" class="cj">.</label>
        <label id="ppas2" class="cj">.</label>
        <label id="ppas3" class="cj">.</label>
        <label id="ppas4" class="cj">.</label>
      </groupbox>
    </column>
  </columns>

  <columns>
    <column>
      <groupbox class="groupbox" id="indicatif">
        <label class="sub_header">Indicatif</label>
        <label id="ipre_temps" class="temps">Présent</label>
        <label id="ipre1" class="cj">.</label>
        <label id="ipre2" class="cj">.</label>
        <label id="ipre3" class="cj">.</label>
        <label id="ipre4" class="cj">.</label>
        <label id="ipre5" class="cj">.</label>
        <label id="ipre6" class="cj">.</label>

        <label id="iimp_temps" class="temps">Imparfait</label>
        <label id="iimp1" class="cj">.</label>
        <label id="iimp2" class="cj">.</label>
        <label id="iimp3" class="cj">.</label>
        <label id="iimp4" class="cj">.</label>
        <label id="iimp5" class="cj">.</label>
        <label id="iimp6" class="cj">.</label>

        <label id="ipsi_temps" class="temps">Passé simple</label>
        <label id="ipsi1" class="cj">.</label>
        <label id="ipsi2" class="cj">.</label>
        <label id="ipsi3" class="cj">.</label>
        <label id="ipsi4" class="cj">.</label>
        <label id="ipsi5" class="cj">.</label>
        <label id="ipsi6" class="cj">.</label>

        <label id="ifut_temps" class="temps">Futur</label>
        <label id="ifut1" class="cj">.</label>
        <label id="ifut2" class="cj">.</label>
        <label id="ifut3" class="cj">.</label>
        <label id="ifut4" class="cj">.</label>
        <label id="ifut5" class="cj">.</label>
        <label id="ifut6" class="cj">.</label>
      </groupbox>
      <description id="smallnote">Ce verbe n’a pas encore été vérifié. C’est pourquoi les options “pronominal” et “temps composés” sont désactivées.</description>
    </column>

    <column>
      <groupbox class="groupbox" id="subjonctif">
        <label class="sub_header">Subjonctif</label>
        <label id="spre_temps" class="temps">Présent</label>
        <label id="spre1" class="cj">.</label>
        <label id="spre2" class="cj">.</label>
        <label id="spre3" class="cj">.</label>
        <label id="spre4" class="cj">.</label>
        <label id="spre5" class="cj">.</label>
        <label id="spre6" class="cj">.</label>

        <label id="simp_temps" class="temps">Imparfait</label>
        <label id="simp1" class="cj">.</label>
        <label id="simp2" class="cj">.</label>
        <label id="simp3" class="cj">.</label>
        <label id="simp4" class="cj">.</label>
        <label id="simp5" class="cj">.</label>
        <label id="simp6" class="cj">.</label>
      </groupbox>

      <groupbox class="groupbox" id="conditionnel">
        <label class="sub_header">Conditionnel</label>
        <label id="conda_temps" class="temps">Présent</label>
        <label id="conda1" class="cj">.</label>
        <label id="conda2" class="cj">.</label>
        <label id="conda3" class="cj">.</label>
        <label id="conda4" class="cj">.</label>
        <label id="conda5" class="cj">.</label>
        <label id="conda6" class="cj">.</label>

        <label id="condb_temps" class="temps">.</label>
        <label id="condb1" class="cj">.</label>
        <label id="condb2" class="cj">.</label>
        <label id="condb3" class="cj">.</label>
        <label id="condb4" class="cj">.</label>
        <label id="condb5" class="cj">.</label>
        <label id="condb6" class="cj">.</label>
      </groupbox>
    </column>
  </columns>

  <script type="application/javascript" src="resource://grammalecte/graphspell/helpers.js"/>
  <script type="application/javascript" src="resource://grammalecte/fr/conj.js"/>
  <script type="application/javascript" src="conjugueur.js"/>
</dialog>

Deleted gc_lang/fr/mailext/content/gc_options.css version [c585d5d70e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* CSS */

.section {
	font-size: 16px;
	font-weight: bold;
	color: hsl(210, 50%, 50%);
}

.dialogheader-title {
  margin: 5px;
  padding: 5px 8px;
  border: 1px solid hsl(210, 50%, 80%);
  background-color: hsl(210, 50%, 50%);
  color: hsl(210, 10%, 90%);
  font-size: larger;
  font-weight: bold;
}

Deleted gc_lang/fr/mailext/content/gc_options.js version [050fb882b6].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53





















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// JavaScript

const Cc = Components.classes;
const Ci = Components.interfaces;
// const Cu = Components.utils;
const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");


var oOptControl = {
    oOptions: null,
    load: function () {
        this._setDialogOptions(false);
        this.listen();
    },
    listen: function () {
        document.addEventListener("dialogaccept", (event) => {
            this.save();
        });
        document.addEventListener("dialogextra1", (event) => {
            this.reset();
        });
    },
    _setDialogOptions: function (bDefaultOptions=false) {
        try {
            sOptions = bDefaultOptions ? prefs.getCharPref("sGCDefaultOptions") : prefs.getCharPref("sGCOptions");
            this.oOptions = JSON.parse(sOptions);
            for (let sParam in this.oOptions) {
                if (document.getElementById("option_"+sParam) !== null) {
                    document.getElementById("option_"+sParam).checked = this.oOptions[sParam];
                }
            }
        }
        catch (e) {
            console.error(e);
        }
    },
    save: function () {
        try {
            for (let xNode of document.getElementsByClassName("option")) {
                this.oOptions[xNode.id.slice(7)] = xNode.checked;
            }
            prefs.setCharPref("sGCOptions", JSON.stringify(this.oOptions));
        }
        catch (e) {
            console.error(e);
        }
    },
    reset: function () {
        this._setDialogOptions(true);
    }
}

oOptControl.load();

Deleted gc_lang/fr/mailext/content/gc_options.xul version [2d497a7dd0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://grammarchecker/content/gc_options.css" type="text/css"?>

<!DOCTYPE dialog SYSTEM "chrome://grammarchecker/locale/gc_options.dtd">

<dialog
  id="grammalecte-gcoptions-window"
  title="&window.title;"
  orient="vertical"
  buttons="accept, cancel, extra1"
  buttonlabelextra1="&defaultbutton.label;"
  defaultButton="accept"
  width="400"
  onload="document.getElementById('grammalecte-gcoptions-window').centerWindowOnScreen();"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <!-- Other elements go here -->

  <div class="dialogheader-title">&dialogheader.label;</div>

  <tabbox id="tabs_options" selectedIndex="0">
    <tabs>
${sXULTabs}
    </tabs>
    <tabpanels>
${sXULTabPanels}
    </tabpanels>
  </tabbox>

  <script type="application/javascript" src="gc_options.js" />

</dialog>

Deleted gc_lang/fr/mailext/content/options.css version [b5017553f4].

1
2
3
4
5
6
7
8
9
10
11
12












-
-
-
-
-
-
-
-
-
-
-
-
/* CSS */


.dialogheader-title {
  margin: 5px;
  padding: 5px 8px;
  border: 1px solid hsl(210, 50%, 80%);
  background-color: hsl(210, 50%, 50%);
  color: hsl(210, 10%, 90%);
  font-size: larger;
  font-weight: bold;
}

Deleted gc_lang/fr/mailext/content/options.js version [9da0d898f3].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40








































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// JavaScript

"use strict";


const Cc = Components.classes;
const Ci = Components.interfaces;
// const Cu = Components.utils;
const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");


var oOptControl = {

    load: function () {
        try {
            document.getElementById('check_signature').checked = prefs.getBoolPref('bCheckSignature');
        }
        catch (e) {
            console.error(e);
        }
        this.listen();
    },

    listen: function () {
        document.addEventListener("dialogaccept", (event) => {
            this.save();
        });
    },

    save: function () {
        try {
            prefs.setBoolPref('bCheckSignature', document.getElementById('check_signature').checked);
        }
        catch (e) {
            console.error(e);
        }
    }
}

oOptControl.load();

Deleted gc_lang/fr/mailext/content/options.xul version [3943bf3117].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://grammarchecker/content/options.css" type="text/css"?>

<!DOCTYPE dialog SYSTEM "chrome://grammarchecker/locale/options.dtd">

<dialog
  id="grammalecte-options-window"
  title="&window.title;"
  orient="vertical"
  buttons="accept, cancel"
  defaultButton="accept"
  width="400"
  onload="document.getElementById('grammalecte-options-window').centerWindowOnScreen();"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <!-- Other elements go here -->

  <div class="dialogheader-title">&dialogheader.label;</div>

  <checkbox id="check_signature" label="&check_signature.label;" accesskey="&check_signature.accesskey;" />

  <script type="application/javascript" src="options.js" />

</dialog>

Deleted gc_lang/fr/mailext/content/overlay.css version [680f0ace85].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164




































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#grammarchecker-toolbar-button {
    list-style-image: url("chrome://grammarchecker/skin/grammarcheck.png");
}
[iconsize="small"] #grammarchecker-toolbar-button {
    list-style-image: url("chrome://grammarchecker/skin/grammarcheck_small.png");
}
#grammarchecker-toolbar-button[disabled="true"] {
    list-style-image: url("chrome://grammarchecker/skin/grammarcheck_disabled.png");
}
[iconsize="small"] #grammarchecker-toolbar-button[disabled="true"] {
    list-style-image: url("chrome://grammarchecker/skin/grammarcheck_small_disabled.png");
}

#grammalecte-menu {
    list-style-image: url("chrome://grammarchecker/skin/grammarcheck.png");
}
menuitem#gl-item-analyze {
    list-style-image: url('chrome://grammarchecker/skin/grammarcheck.png');
}

#textformatter-panel {
    overflow: auto;
    height: 500px;
    max-height: 650px;
    color: hsl(0, 0%, 0%);
}
#textformatter-title {
    margin-top: 10px;
}
#textformatter-commands {
    margin: 10px 0;
}
#textformatter-infomsg {
    padding: 5px;
    font-size: 10px;
}
.optiongroup {
    color: hsl(210, 50%, 40%);
    font-size: 14px;
    font-weight: bold;
}
#textformatter-progressbar {
    width: 470px;
}
#textformatter-timer {
    padding: 5px;
}


#grammarchecker-panel {
    overflow: auto;
    margin-left: 0.5em;
    height: 400px;
    max-height: 600px;
}

#grammalecte-title {
    margin-top: 10px;
}

#grammalecte-infobox {
    display: block;
    margin: 20px 10px 5px 10px;
    padding: 10px;
    background-color: hsl(210, 20%, 40%);
    border-radius: 3px;
    color: hsl(210, 50%, 96%);
    font-weight: bold;
}
#grammalecte-info {
    padding: 1px 5px;
}
#closebutton {
    padding: 1px 5px;
    background-color: hsl(0, 50%, 50%);
    color: hsl(0, 10%, 96%);
    border-radius: 2px;
    cursor: pointer;
}

#grammalecte-errors div {
    display: block;
    /*display: list-item;
    list-style-position: inside;*/
    margin-top: 10px;
}
#grammalecte-errors p {
    display: block;
    margin-left: 10px;
    color: hsl(0, 0%, 0%);
}
#grammalecte-errors p.paragraph {
    margin-top: 20px;
    font-size: 16px;
    font-family: "Courier New", Courier, "Lucida Sans Typewriter", "Lucida Typewriter", monospace;
}
#grammalecte-errors p.message {
    margin-left: 20px;
}
#grammalecte-errors p.moreinfo {
    margin-left: 40px;
}
#grammalecte-errors p.suggestions {
    margin-left: 40px;
    color: hsl(120, 5%, 33%);
}
#grammalecte-errors span.suggestions_button {
    padding: 1px 6px;
    background-color: hsl(120, 40%, 60%);
    color: hsl(120, 10%, 96%);
    border-radius: 2px;
    cursor: pointer;
}
#grammalecte-errors {
    display: block;
}

a {
    font-weight: bold;
    color: hsl(30, 50%, 50%);
    text-decoration: underline;
    cursor: pointer;
}
.error {
    /* default color */
    background-color: hsl(210, 50%, 50%);
    color: hsl(210, 10%, 96%);
    font-weight: bold;
    border-radius: 3px;
    /*border-bottom: 2px solid hsl(210, 50%, 50%);*/
}
.errornum {
    color: hsl(210, 10%, 30%);
    font-weight: bold;
}
.sugg {
    padding: 1px 6px;
    background-color: hsl(120, 50%, 30%);
    color: hsl(210, 10%, 90%);
    border-radius: 2px;
    font-weight: bold;
    cursor: pointer;
}
.debug_info {
    color: hsl(0, 50%, 50%);
    font-style: italic;
}

.spell {
    background-color: hsl(0, 50%, 50%);
    color: hsl(0, 0%, 96%);
    border-radius: 3px;
}


.dialogheader-title {
    margin: 5px;
    padding: 5px 8px;
    border: 1px solid hsl(210, 50%, 80%);
    background-color: hsl(210, 50%, 50%);
    color: hsl(210, 10%, 90%);
    font-size: larger;
    font-weight: bold;
}

Deleted gc_lang/fr/mailext/content/overlay.js version [2bffe86e4e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
















































































































































































































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// JavaScript

"use strict";


const Cc = Components.classes;
const Ci = Components.interfaces;
//const Cu = Components.utils;
//const { require } = Cu.import("resource://gre/modules/commonjs/toolkit/require.js", {});

const { BasePromiseWorker } = ChromeUtils.import('resource://gre/modules/PromiseWorker.jsm', {});
const xGrammalectePrefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");

//const text = require("resource://grammalecte/text.js");
//const tf = require("resource://grammalecte/fr/textformatter.js");


const oConverterToExponent = {
    dNumbers: new Map ([
        ["1", "¹"], ["2", "²"], ["3", "³"], ["4", "⁴"], ["5", "⁵"],
        ["6", "⁶"], ["7", "⁷"], ["8", "⁸"], ["9", "⁹"], ["0", "⁰"]
    ]),
    convert: function (sText) {
        let sRes = "";
        for (let c of sText) {
            sRes += (this.dNumbers.has(c)) ? this.dNumbers.get(c) : "⁻";
        }
        return sRes;
    }
};


var oGrammarChecker = {
    // you must use var to be able to call this object from elsewhere
    xGCEWorker: null,
    loadGC: function () {
        if (this.xGCEWorker === null) {
            // Grammar checker
            console.log('Loading Grammalecte');
            this.xGCEWorker = new BasePromiseWorker('chrome://promiseworker/content/gce_worker.js');
            let that = this;
            let xPromise = this.xGCEWorker.post('loadGrammarChecker', [xGrammalectePrefs.getCharPref("sGCOptions"), "Thunderbird"]);
            xPromise.then(
                function (aVal) {
                    console.log(aVal);
                    xGrammalectePrefs.setCharPref("sGCOptions", aVal);
                    // spelling dictionary
                    if (xGrammalectePrefs.getCharPref("sMainDicName")) {
                        let sMainDicName = xGrammalectePrefs.getCharPref("sMainDicName");
                        if (sMainDicName == "fr-classic.json" || sMainDicName == "fr-reform.json") {
                            that.xGCEWorker.post("setDictionary", ["main", sMainDicName]);
                        }
                    }
                    // personal dictionary
                    if (xGrammalectePrefs.getBoolPref("bPersonalDictionary")) {
                        let sDicJSON = oFileHandler.loadFile("fr.personal.json");
                        if (sDicJSON) {
                            that.xGCEWorker.post('setDictionary', ["personal", sDicJSON]);
                        }
                    }
                },
                function (aReason) { console.log('Promise rejected - ', aReason); }
            ).catch(
                function (aCaught) { console.log('Promise Error - ', aCaught); }
            );
        }
    },
    fullTests: function () {
        console.log('Performing tests... Wait...');
        let xPromise = this.xGCEWorker.post('fullTests', ['{"nbsp":true, "esp":true, "unit":true, "num":true}']);
        xPromise.then(
            function (aVal) {
                console.log('Done.');
                console.log(aVal);
            },
            function (aReason) { console.log('Promise rejected', aReason); }
        ).catch(
            function (aCaught) { console.log('Promise Error', aCaught); }
        );
    },
    test: function (sText) {
        console.log("Test...");
        let xPromise = this.xGCEWorker.post('parse', [sText, "FR", true]);
        xPromise.then(
            function (aVal) {
                let lErr = JSON.parse(aVal);
                if (lErr.length > 0) {
                    for (let dErr of lErr) {
                        console.log(text.getReadableError(dErr));
                    }
                } else {
                    console.log("no error found");
                }
            },
            function (aReason) { console.log('Promise rejected', aReason); }
        ).catch(
            function (aCaught) { console.log('Promise Error', aCaught); }
        );
    },
    setOptions: function () {
        console.log('Set options');
        let xPromise = this.xGCEWorker.post('setOptions', [xGrammalectePrefs.getCharPref("sGCOptions")]);
        xPromise.then(
            function (aVal) {
                console.log(aVal);
                xGrammalectePrefs.setCharPref("sGCOptions", aVal);
            },
            function (aReason) { console.log('Promise rejected', aReason); }
        ).catch(
            function (aCaught) { console.log('Promise Error', aCaught); }
        );
    },
    resetOptions: function () {
        let xPromise = this.xGCEWorker.post('resetOptions');
        xPromise.then(
            function (aVal) {
                console.log(aVal);
                xGrammalectePrefs.setCharPref("sGCOptions", aVal);
            },
            function (aReason) { console.log('Promise rejected', aReason); }
        ).catch(
            function (aCaught) { console.log('Promise Error', aCaught); }
        );
    },
    parse: async function () {
        this.clearPreview();
        this.openPanel();
        this.setInfo("Analyse en cours…");
        try {
            let xEditor = new Editor();
            let nParagraph = 0;
            let bIsError = false;
            for (let [iParagraph, sParagraph] of xEditor.getParagraphs()) {
                if (sParagraph.trim() !== "") {
                    let sRes = await this.xGCEWorker.post('parseAndSpellcheck', [sParagraph, "FR", false, false]);
                    let oRes = JSON.parse(sRes);
                    if (oRes.aGrammErr.length > 0 || oRes.aSpellErr.length > 0) {
                        document.getElementById("grammalecte-errors").appendChild(this.createResultNode(xEditor, sParagraph, iParagraph, oRes.aGrammErr, oRes.aSpellErr));
                        bIsError = true;
                    }
                    nParagraph += 1;
                }
            }
            if (bIsError === false) {
                let xNodeP = document.createElement("p");
                xNodeP.setAttribute("class", "message");
                xNodeP.textContent = "Aucune erreur détectée…";
                document.getElementById("grammalecte-errors").appendChild(xNodeP);
            }
            this.setInfo("Nombre de paragraphes analysés : " + nParagraph);
        }
        catch (e) {
            this.setInfo("Erreur : " + e.message);
            console.error(e);
        }
    },
    createResultNode: function (xEditor, sParagraph, iParagraph, aGrammErr, aSpellErr) {
        let xResultNode = document.createElement("div");
        xResultNode.setAttribute("id", "resnode" + iParagraph);
        this.fillResultNode(xResultNode, xEditor, sParagraph, iParagraph, aGrammErr, aSpellErr);
        return xResultNode;
    },
    reparseParagraph: function (xEditor, iParagraph) {
        try {
            let that = this;
            let xResultNode = document.getElementById("resnode"+iParagraph);
            xResultNode.textContent = "…………… réanalyse en cours ……………";
            let sParagraph = xEditor.getParagraph(iParagraph);
            let xPromise = this.xGCEWorker.post('parseAndSpellcheck', [sParagraph, "FR", false, false]);
            xPromise.then(function (res) {
                xResultNode.textContent = "";
                let oRes = JSON.parse(res);
                if (oRes.aGrammErr.length > 0 || oRes.aSpellErr.length > 0) {
                    that.fillResultNode(xResultNode, xEditor, sParagraph, iParagraph, oRes.aGrammErr, oRes.aSpellErr);
                }
            }, function (res) {
                xResultNode.textContent = "Erreur: " + res;
            });
        }
        catch (e) {
            console.error(e);
        }
    },
    fillResultNode: function (xResultNode, xEditor, sParagraph, iParagraph, aGrammErr, aSpellErr) {
        try {
            if (aGrammErr.length === 0  &&  aSpellErr.length === 0) {
                return null;
            }
            aGrammErr.push(...aSpellErr);
            aGrammErr.sort(function (a, b) {
                if (a["nStart"] < b["nStart"])
                    return -1;
                if (a["nStart"] > b["nStart"])
                    return 1;
                return 0;
            });
            let xParagraphNode = document.createElement("p");
            let lNodeError = [];
            let nEndLastErr = 0;
            let nError = 1;
            xParagraphNode.setAttribute("class", "paragraph");
            for (let dErr of aGrammErr) {
                let nStart = dErr["nStart"];
                let nEnd = dErr["nEnd"];
                if (nStart >= nEndLastErr) {
                    xParagraphNode.appendChild(document.createTextNode(this._purgeTags(sParagraph.slice(nEndLastErr, nStart))));
                    let xNodeError = document.createElement("b");
                    if (dErr['sType'] !== 'WORD') {
                        xNodeError.setAttribute("class", "error");
                        xNodeError.textContent = oConverterToExponent.convert(nError.toString()) + sParagraph.slice(nStart, nEnd);
                        xNodeError.style.backgroundColor = dErr["aColor"];
                        xParagraphNode.appendChild(xNodeError);
                        lNodeError.push(this._createNodeGCErrorDescription(xEditor, nError, dErr, iParagraph));
                    }
                    else {
                        xNodeError.setAttribute("class", "error spell");
                        xNodeError.textContent = oConverterToExponent.convert(nError.toString()) + sParagraph.slice(nStart, nEnd);
                        xParagraphNode.appendChild(xNodeError);
                        lNodeError.push(this._createNodeSpellErrorDescription(xEditor, nError, dErr, iParagraph));
                    }
                    nEndLastErr = nEnd;
                    nError += 1;
                }
            }
            xParagraphNode.appendChild(document.createTextNode(this._purgeTags(sParagraph.slice(nEndLastErr))));
            xResultNode.appendChild(xParagraphNode);
            for (let xNode of lNodeError) {
                xResultNode.appendChild(xNode);
            }
        }
        catch (e) {
            console.error(e);
            xResultNode.textContent = "# Error: " + e.message;
        }
    },
    _createNodeGCErrorDescription: function (xEditor, nError, dErr, iParagraph) {
        let xNodeDiv = document.createElement("div");
        let that = this;
        // message
        let xNodeMessage = document.createElement("p");
        xNodeMessage.setAttribute("class", "message");
        let xNodeErrorNumber = document.createElement("b");
        xNodeErrorNumber.setAttribute("class", "errornum");
        xNodeErrorNumber.textContent = "[" + nError + "] ";
        xNodeMessage.appendChild(xNodeErrorNumber);
        xNodeMessage.appendChild(document.createTextNode(" " + dErr["sMessage"].replace(/&nbsp;/g, " ") + " "));
        if (false) {
            // debug info
            let xNodeDebug = document.createElement("span");
            xNodeDebug.setAttribute("class", "debug_info");
            xNodeDebug.textContent = " #" + dErr["sRuleId"] + " #" + dErr["sLineId"];
            xNodeMessage.appendChild(xNodeDebug);
        }
        xNodeDiv.appendChild(xNodeMessage);
        // URL
        if (dErr["URL"]) {
            let xNodeP = document.createElement("p");
            xNodeP.setAttribute("class", "moreinfo");
            xNodeP.appendChild(document.createTextNode("→ "));
            let xNodeURL = document.createElement("a");
            xNodeURL.setAttribute("href", dErr["URL"]);
            xNodeURL.textContent = "Plus d’informations…";
            xNodeURL.addEventListener("click", function (e) {
                that.openInTabURL(dErr["URL"]);
            });
            xNodeP.appendChild(xNodeURL);
            xNodeDiv.appendChild(xNodeP);
        }
        // suggestions
        if (dErr["aSuggestions"].length > 0) {
            let xNodeSuggLine = document.createElement("p");
            xNodeSuggLine.setAttribute("class", "suggestions");
            xNodeSuggLine.textContent = "Suggestions : ";
            let n = 0;
            for (let sSugg of dErr["aSuggestions"]) {
                if (n > 0) {
                    xNodeSuggLine.appendChild(document.createTextNode(" "));
                }
                let xNodeSugg = document.createElement("span");
                xNodeSugg.setAttribute("class", "sugg");
                xNodeSugg.textContent = sSugg.replace(" ", " "); // use nnbsp
                xNodeSugg.addEventListener("click", function (e) {
                    xEditor.changeParagraph(iParagraph, sSugg, dErr["nStart"], dErr["nEnd"]);
                    xNodeDiv.textContent = "";
                    that.reparseParagraph(xEditor, iParagraph);
                });
                xNodeSuggLine.appendChild(xNodeSugg);
                n += 1;
            }
            xNodeDiv.appendChild(xNodeSuggLine);
        }
        return xNodeDiv;
    },
    _purgeTags: function (sText) {
        sText = sText.replace(/<br ?\/?>/ig, " ");
        sText = sText.replace(/<font size="[+-]\d+">/g, "");
        return sText.replace(/<\/? ?[a-zA-Z]+ ?>/g, "");
    },
    _createNodeSpellErrorDescription: function (xEditor, nError, dErr, iParagraph) {
        let xNodeDiv = document.createElement("div");
        let that = this;
        // message
        let xNodeMessage = document.createElement("p");
        xNodeMessage.setAttribute("class", "message");
        let xNodeErrorNumber = document.createElement("b");
        xNodeErrorNumber.setAttribute("class", "errornum");
        xNodeErrorNumber.textContent = "[" + nError + "] ";
        xNodeMessage.appendChild(xNodeErrorNumber);
        xNodeMessage.appendChild(document.createTextNode(" Mot inconnu du dictionnaire. "));
        xNodeDiv.appendChild(xNodeMessage);
        // suggestions
        let xNodeSuggLine = document.createElement("p");
        xNodeSuggLine.setAttribute("class", "suggestions");
        let xNodeSuggButton = document.createElement("span");
        xNodeSuggButton.setAttribute("class", "suggestions_button");
        xNodeSuggButton.textContent = "Suggestions : ";
        xNodeSuggButton.addEventListener("click", (e) => {
            let xPromise = this.xGCEWorker.post('suggest', [dErr['sValue'], 10]);
            xPromise.then(
                function (sVal) {
                    if (sVal != "") {
                        let lSugg = sVal.split("|");
                        let n = 0;
                        for (let sSugg of lSugg) {
                            xNodeSuggLine.appendChild(document.createTextNode(" "));
                            let xNodeSugg = document.createElement("span");
                            xNodeSugg.setAttribute("class", "sugg");
                            xNodeSugg.textContent = sSugg;
                            xNodeSugg.addEventListener("click", function (e) {
                                xEditor.changeParagraph(iParagraph, xNodeSugg.textContent, dErr["nStart"], dErr["nEnd"]);
                                xNodeDiv.textContent = "";
                                that.reparseParagraph(xEditor, iParagraph);
                            });
                            xNodeSuggLine.appendChild(xNodeSugg);
                            n += 1;
                        }
                    } else {
                        xNodeSuggLine.appendChild(document.createTextNode("Aucune suggestion."));
                    }
                },
                function (aReason) { console.error('Promise rejected - ', aReason); }
            ).catch(
                function (aCaught) { console.error('Promise Error - ', aCaught); }
            );
        });
        xNodeSuggLine.appendChild(xNodeSuggButton);
        xNodeDiv.appendChild(xNodeSuggLine);
        return xNodeDiv;
    },
    loadUI: function () {
        this._strings = document.getElementById("grammarchecker-strings");
        let that = this;
        let nsGrammarCommand = {
            isCommandEnabled: function (aCommand, dummy) {
                return (IsDocumentEditable() && !IsInHTMLSourceMode());
            },
            getCommandStateParams: function (aCommand, aParams, aRefCon) {},
            doCommandParams: function (aCommand, aParams, aRefCon) {},
            doCommand: function (aCommand) {
                that.onParseText(aCommand);
            }
        };
        let xCommandTable = GetComposerCommandTable();
        xCommandTable.registerCommand("cmd_grammar", nsGrammarCommand);
        let sButtonId = "grammarchecker-toolbar-button";
        let sButtonId2 = "grammalecte-menu";
        let xNavBar  = document.getElementById("composeToolbar2");
        let lCurSet  = xNavBar.currentSet.split(",");
        if (lCurSet.indexOf(sButtonId) == -1) {
            let iPos = lCurSet.indexOf("spellingButton") + 1 || lCurSet.length;
            let aSet = lCurSet.slice(0, iPos).concat(sButtonId).concat(sButtonId2).concat(lCurSet.slice(iPos));
            xNavBar.setAttribute("currentset", aSet.join(","));
            //xNavBar.currentSet = aSet.join(",");
            Services.xulStore.persist(xNavBar, "currentset");
            //Ci.BrowserToolboxCustomizeDone(true);
        }
    },
    clearPreview: function () {
        let xPreview = document.getElementById("grammalecte-errors");
        while (xPreview.firstChild) {
            xPreview.removeChild(xPreview.firstChild);
        };
        let xEditor = GetCurrentEditor();
        if (xEditor != null) {
            try {
                xEditor.QueryInterface(Ci.nsIEditorStyleSheets);
                xEditor.addOverrideStyleSheet("chrome://grammarchecker/content/overlay.css");
            }
            catch (e) {
                console.error(e);
            }
        }
        this.setInfo("[vide]");
    },
    setInfo: function (sText) {
        document.getElementById("grammalecte-info").textContent = sText;
    },
    openPanel: function () {
        document.getElementById("textformatter-splitter").setAttribute("state", "collapsed");
        document.getElementById("grammarchecker-splitter").setAttribute("state", "open");
    },
    closePanel: function () {
        document.getElementById("grammarchecker-splitter").setAttribute("state", "collapsed");
    },
    openDialog: function (sWhat, sName="", sOptions="") {
        try {
            window.openDialog(sWhat, sName, sOptions);
        }
        catch (e) {
            console.error(e);
        }
    },
    openInTabURL: function (sURL) {
        // method found in S3.Google.Translator
        try {
            let xWM = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
            let xWin = xWM.getMostRecentWindow("mail:3pane");
            let xTabmail = xWin.document.getElementById('tabmail');
            xWin.focus();
            if (xTabmail) {
                xTabmail.openTab('contentTab', { contentPage: sURL });
            }
        }
        catch (e) {
            console.error(e);
        }
    },
    openInBrowserURL: function (sURL) {
        // method found in S3.Google.Translator
        try {
            openURL(sURL);
        }
        catch (e) {
            console.error(e);
        }
    },
    onParseText: function (e) {
        this.parse();
    },
    onClosePanel: function (e) {
        this.closePanel();
    },
    onOpenGCOptions: function (e) {
        let that = this;
        let xPromise = this.xGCEWorker.post('getDefaultOptions');
        xPromise.then(
            function (aVal) {
                console.log(aVal);
                xGrammalectePrefs.setCharPref("sGCDefaultOptions", aVal);
            },
            function (aReason) { console.log('Promise rejected', aReason); }
        ).catch(
            function (aCaught) { console.log('Promise Error', aCaught); }
        ).then(
            function () {
                that.openDialog("chrome://grammarchecker/content/gc_options.xul", "", "chrome, dialog, modal, resizable=no");
                that.setOptions();
            },
            function (aReason) { console.log('Error options dialog', aReason); }
        ).catch(
            function (aCaught) { console.log('Error', aCaught); }
        );
    },
    onOpenSpellOptions: function (e) {
        this.openDialog("chrome://grammarchecker/content/spell_options.xul", "", "chrome, dialog, modal, resizable=no");
    },
    onOpenOptions: function (e) {
        this.openDialog("chrome://grammarchecker/content/options.xul", "", "chrome, dialog, modal, resizable=no");
    },
    onOpenTextFormatter: function (e) {
        oTextFormatter.openPanel();
    },
    onOpenConjugueur: function (e) {
        this.openDialog("chrome://grammarchecker/content/conjugueur.xul", "", "chrome, resizable=no");
    },
    onOpenLexiconEditor: function (e) {
        this.openDialog("chrome://grammarchecker/content/lex_editor.xul", "", "chrome, resizable=no");
    },
    onAbout: function (e) {
        this.openDialog("chrome://grammarchecker/content/about.xul", "", "chrome, dialog, modal, resizable=no");
    }
};


var oTextFormatter = {
    init: function () {
        try {
            this.closePanel();
            this.listen();
            let sTFOptions = xGrammalectePrefs.getCharPref("sTFOptions");
            if (sTFOptions !== "") {
                this.setOptionsInPanel(JSON.parse(sTFOptions));
                this.resetProgressBar();
            } else {
                this.reset();
            }
        }
        catch (e) {
            console.error(e);
        }
    },
    listen: function () {
        window.addEventListener("click", (xEvent) => {
            let xElem = xEvent.target;
            if (xElem.id && xElem.id.startsWith("o_group_")) {
                this.switchGroup(xElem.id);
                this.resetProgressBar();
            }
        }, false);
    },
    apply: function () {
        try {
            this.saveOptions();
            this.resetProgressBar();
            let xEditor = new Editor();
            let sText = xEditor.getContent();
            let iParagraph = 0;
            sText = this.applyOptions(sText);
            for (let sParagraph of text.getParagraph(sText)) {
                xEditor.writeParagraph(iParagraph, sParagraph);
                iParagraph += 1;
            }
        }
        catch (e) {
            console.error(e);
        }
    },
    saveOptions: function () {
        let oOptions = {};
        for (let xNode of document.getElementsByClassName("option")) {
            oOptions[xNode.id] = xNode.checked;
        }
        //console.log("save options: " + JSON.stringify(oOptions));
        xGrammalectePrefs.setCharPref("sTFOptions", JSON.stringify(oOptions));
    },
    setOptionsInPanel: function (oOptions) {
        for (let sOptName in oOptions) {
            //console.log(sOptName + ":" + oOptions[sOptName]);
            if (document.getElementById(sOptName) !== null) {
                document.getElementById(sOptName).checked = oOptions[sOptName];
                if (sOptName.startsWith("o_group_")) {
                    this.switchGroup(sOptName);
                }
                if (document.getElementById("res_"+sOptName) !== null) {
                    document.getElementById("res_"+sOptName).textContent = "";
                }
            }
        }
    },
    switchGroup: function (sOptName) {
        if (document.getElementById(sOptName).checked) {
            document.getElementById(sOptName.slice(2)).style.opacity = 1;
        } else {
            document.getElementById(sOptName.slice(2)).style.opacity = 0.3;
        }
    },
    reset: function () {
        try {
            this.resetProgressBar();
            for (let xNode of document.getElementsByClassName('option')) {
                xNode.checked = (xNode.getAttribute('data-default') === "true");
                if (xNode.id.startsWith("o_group_")) {
                    this.switchGroup(xNode.id);
                }
            }
        }
        catch (e) {
            console.error(e);
        }
    },
    resetProgressBar: function () {
        document.getElementById('textformatter-progressbar').value = 0;
        document.getElementById('textformatter-timer').textContent = "";
    },
    getTimeRes: function (n) {
        // returns duration in seconds as string
        if (n < 10) {
            return n.toFixed(3).toString() + " s";
        }
        if (n < 100) {
            return n.toFixed(2).toString() + " s";
        }
        if (n < 1000) {
            return n.toFixed(1).toString() + " s";
        }
        return n.toFixed().toString() + " s";
    },
    openPanel: function () {
        document.getElementById("grammarchecker-splitter").setAttribute("state", "collapsed");
        document.getElementById("textformatter-splitter").setAttribute("state", "open");
    },
    closePanel: function () {
        document.getElementById("textformatter-splitter").setAttribute("state", "collapsed");
    },
    onOpenPanel: function (e) {
        this.openPanel();
    },
    onClosePanel: function (e) {
        this.closePanel();
    },
    onApply: function (e) {
        this.apply();
    },
    onReset: function (e) {
        this.reset();
    },
    //
    applyOptions: function (sText) {
        try {
            const t0 = Date.now();
            //window.setCursor("wait"); // change pointer
            document.getElementById('textformatter-progressbar').value = 0;
            document.getElementById('textformatter-progressbar').max = 6;
            let n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0, n7 = 0;

            // espaces surnuméraires
            if (document.getElementById("o_group_ssp").checked) {
                if (document.getElementById("o_end_of_paragraph").checked) {
                    [sText, n1] = this.formatText(sText, "end_of_paragraph");
                    document.getElementById('res_o_end_of_paragraph').textContent = n1;
                }
                if (document.getElementById("o_between_words").checked) {
                    [sText, n1] = this.formatText(sText, "between_words");
                    document.getElementById('res_o_between_words').textContent = n1;
                }
                if (document.getElementById("o_start_of_paragraph").checked) {
                    [sText, n1] = this.formatText(sText, "start_of_paragraph");
                    document.getElementById('res_o_start_of_paragraph').textContent = n1;
                }
                if (document.getElementById("o_before_punctuation").checked) {
                    [sText, n1] = this.formatText(sText, "before_punctuation");
                    document.getElementById('res_o_before_punctuation').textContent = n1;
                }
                if (document.getElementById("o_within_parenthesis").checked) {
                    [sText, n1] = this.formatText(sText, "within_parenthesis");
                    document.getElementById('res_o_within_parenthesis').textContent = n1;
                }
                if (document.getElementById("o_within_square_brackets").checked) {
                    [sText, n1] = this.formatText(sText, "within_square_brackets");
                    document.getElementById('res_o_within_square_brackets').textContent = n1;
                }
                if (document.getElementById("o_within_quotation_marks").checked) {
                    [sText, n1] = this.formatText(sText, "within_quotation_marks");
                    document.getElementById('res_o_within_quotation_marks').textContent = n1;
                }
                document.getElementById("o_group_ssp").checked = false;
                this.switchGroup("o_group_ssp");
            }
            document.getElementById('textformatter-progressbar').value = 1;

            // espaces insécables
            if (document.getElementById("o_group_nbsp").checked) {
                if (document.getElementById("o_nbsp_before_punctuation").checked) {
                    [sText, n1] = this.formatText(sText, "nbsp_before_punctuation");
                    [sText, n2] = this.formatText(sText, "nbsp_repair");
                    document.getElementById('res_o_nbsp_before_punctuation').textContent = n1 - n2;
                }
                if (document.getElementById("o_nbsp_within_quotation_marks").checked) {
                    [sText, n1] = this.formatText(sText, "nbsp_within_quotation_marks");
                    document.getElementById('res_o_nbsp_within_quotation_marks').textContent = n1;
                }
                if (document.getElementById("o_nbsp_before_symbol").checked) {
                    [sText, n1] = this.formatText(sText, "nbsp_before_symbol");
                    document.getElementById('res_o_nbsp_before_symbol').textContent = n1;
                }
                if (document.getElementById("o_nbsp_within_numbers").checked) {
                    [sText, n1] = this.formatText(sText, "nbsp_within_numbers");
                    document.getElementById('res_o_nbsp_within_numbers').textContent = n1;
                }
                if (document.getElementById("o_nbsp_before_units").checked) {
                    [sText, n1] = this.formatText(sText, "nbsp_before_units");
                    document.getElementById('res_o_nbsp_before_units').textContent = n1;
                }
                if (document.getElementById("o_nbsp_titles").checked) {
                    [sText, n1] = this.formatText(sText, "nbsp_titles");
                    document.getElementById('res_o_nbsp_titles').textContent = n1;
                }
                document.getElementById("o_group_nbsp").checked = false;
                this.switchGroup("o_group_nbsp");
            }
            document.getElementById('textformatter-progressbar').value = 2;

            // espaces manquants
            if (document.getElementById("o_group_typo").checked) {
                if (document.getElementById("o_ts_units").checked) {
                    [sText, n1] = this.formatText(sText, "ts_units");
                    document.getElementById('res_o_ts_units').textContent = n1;
                }
            }
            if (document.getElementById("o_group_space").checked) {
                if (document.getElementById("o_add_space_after_punctuation").checked) {
                    [sText, n1] = this.formatText(sText, "add_space_after_punctuation");
                    [sText, n2] = this.formatText(sText, "add_space_repair");
                    document.getElementById('res_o_add_space_after_punctuation').textContent = n1 - n2;
                }
                if (document.getElementById("o_add_space_around_hyphens").checked) {
                    [sText, n1] = this.formatText(sText, "add_space_around_hyphens");
                    document.getElementById('res_o_add_space_around_hyphens').textContent = n1;
                }
                document.getElementById("o_group_space").checked = false;
                this.switchGroup("o_group_space");
            }
            document.getElementById('textformatter-progressbar').value = 3;

            // suppression
            if (document.getElementById("o_group_delete").checked) {
                if (document.getElementById("o_erase_non_breaking_hyphens").checked) {
                    [sText, n1] = this.formatText(sText, "erase_non_breaking_hyphens");
                    document.getElementById('res_o_erase_non_breaking_hyphens').textContent = n1;
                }
                document.getElementById("o_group_delete").checked = false;
                this.switchGroup("o_group_delete");
            }
            document.getElementById('textformatter-progressbar').value = 4;

            // signes typographiques
            if (document.getElementById("o_group_typo").checked) {
                if (document.getElementById("o_ts_apostrophe").checked) {
                    [sText, n1] = this.formatText(sText, "ts_apostrophe");
                    document.getElementById('res_o_ts_apostrophe').textContent = n1;
                }
                if (document.getElementById("o_ts_ellipsis").checked) {
                    [sText, n1] = this.formatText(sText, "ts_ellipsis");
                    document.getElementById('res_o_ts_ellipsis').textContent = n1;
                }
                if (document.getElementById("o_ts_dash_start").checked) {
                    if (document.getElementById("o_ts_m_dash_start").checked) {
                        [sText, n1] = this.formatText(sText, "ts_m_dash_start");
                    } else {
                        [sText, n1] = this.formatText(sText, "ts_n_dash_start");
                    }
                    document.getElementById('res_o_ts_dash_start').textContent = n1;
                }
                if (document.getElementById("o_ts_dash_middle").checked) {
                    if (document.getElementById("o_ts_m_dash_middle").checked) {
                        [sText, n1] = this.formatText(sText, "ts_m_dash_middle");
                    } else {
                        [sText, n1] = this.formatText(sText, "ts_n_dash_middle");
                    }
                    document.getElementById('res_o_ts_dash_middle').textContent = n1;
                }
                if (document.getElementById("o_ts_quotation_marks").checked) {
                    [sText, n1] = this.formatText(sText, "ts_quotation_marks");
                    document.getElementById('res_o_ts_quotation_marks').textContent = n1;
                }
                if (document.getElementById("o_ts_spell").checked) {
                    [sText, n1] = this.formatText(sText, "ts_spell");
                    document.getElementById('res_o_ts_spell').textContent = n1;
                }
                if (document.getElementById("o_ts_ligature").checked) {
                    // ligatures typographiques : fi, fl, ff, ffi, ffl, ft, st
                    if (document.getElementById("o_ts_ligature_do").checked) {
                        if (document.getElementById("o_ts_ligature_ffi").checked) {
                            [sText, n1] = this.formatText(sText, "ts_ligature_ffi_do");
                        }
                        if (document.getElementById("o_ts_ligature_ffl").checked) {
                            [sText, n2] = this.formatText(sText, "ts_ligature_ffl_do");
                        }
                        if (document.getElementById("o_ts_ligature_fi").checked) {
                            [sText, n3] = this.formatText(sText, "ts_ligature_fi_do");
                        }
                        if (document.getElementById("o_ts_ligature_fl").checked) {
                            [sText, n4] = this.formatText(sText, "ts_ligature_fl_do");
                        }
                        if (document.getElementById("o_ts_ligature_ff").checked) {
                            [sText, n5] = this.formatText(sText, "ts_ligature_ff_do");
                        }
                        if (document.getElementById("o_ts_ligature_ft").checked) {
                            [sText, n6] = this.formatText(sText, "ts_ligature_ft_do");
                        }
                        if (document.getElementById("o_ts_ligature_st").checked) {
                            [sText, n7] = this.formatText(sText, "ts_ligature_st_do");
                        }
                    }
                    if (document.getElementById("o_ts_ligature_undo").checked) {
                        if (document.getElementById("o_ts_ligature_ffi").checked) {
                            [sText, n1] = this.formatText(sText, "ts_ligature_ffi_undo");
                        }
                        if (document.getElementById("o_ts_ligature_ffl").checked) {
                            [sText, n2] = this.formatText(sText, "ts_ligature_ffl_undo");
                        }
                        if (document.getElementById("o_ts_ligature_fi").checked) {
                            [sText, n3] = this.formatText(sText, "ts_ligature_fi_undo");
                        }
                        if (document.getElementById("o_ts_ligature_fl").checked) {
                            [sText, n4] = this.formatText(sText, "ts_ligature_fl_undo");
                        }
                        if (document.getElementById("o_ts_ligature_ff").checked) {
                            [sText, n5] = this.formatText(sText, "ts_ligature_ff_undo");
                        }
                        if (document.getElementById("o_ts_ligature_ft").checked) {
                            [sText, n6] = this.formatText(sText, "ts_ligature_ft_undo");
                        }
                        if (document.getElementById("o_ts_ligature_st").checked) {
                            [sText, n7] = this.formatText(sText, "ts_ligature_st_undo");
                        }
                    }
                    document.getElementById('res_o_ts_ligature').textContent = n1 + n2 + n3 + n4 + n5 + n6 + n7;
                }
                document.getElementById("o_group_typo").checked = false;
                this.switchGroup("o_group_typo");
            }
            document.getElementById('textformatter-progressbar').value = 5;

            // divers
            if (document.getElementById("o_group_misc").checked) {
                if (document.getElementById("o_ordinals_no_exponant").checked) {
                    if (document.getElementById("o_ordinals_exponant").checked) {
                        [sText, n1] = this.formatText(sText, "ordinals_exponant");
                    } else {
                        [sText, n1] = this.formatText(sText, "ordinals_no_exponant");
                    }
                    document.getElementById('res_o_ordinals_no_exponant').textContent = n1;
                }
                if (document.getElementById("o_etc").checked) {
                    [sText, n1] = this.formatText(sText, "etc");
                    document.getElementById('res_o_etc').textContent = n1;
                }
                if (document.getElementById("o_missing_hyphens").checked) {
                    [sText, n1] = this.formatText(sText, "missing_hyphens");
                    document.getElementById('res_o_missing_hyphens').textContent = n1;
                }
                if (document.getElementById("o_ma_word").checked) {
                    [sText, n1] = this.formatText(sText, "ma_word");
                    if (document.getElementById("o_ma_1letter_lowercase").checked) {
                        [sText, n1] = this.formatText(sText, "ma_1letter_lowercase");
                        if (document.getElementById("o_ma_1letter_uppercase").checked) {
                            [sText, n1] = this.formatText(sText, "ma_1letter_uppercase");
                        }
                    }
                    document.getElementById('res_o_ma_word').textContent = n1;
                }
                document.getElementById("o_group_misc").checked = false;
                this.switchGroup("o_group_misc");
            }
            document.getElementById('textformatter-progressbar').value = document.getElementById('textformatter-progressbar').max;
            // end of processing

            //window.setCursor("auto"); // restore pointer
            const t1 = Date.now();
            document.getElementById('textformatter-timer').textContent = this.getTimeRes((t1-t0)/1000);
        }
        catch (e) {
            console.error(e);
        }
        return sText;
    },
    formatText: function (sText, sOptName) {
        let nCount = 0;
        try {
            if (!oReplTable.hasOwnProperty(sOptName)) {
                console.log("# Error. TF: there is no option “" + sOptName+ "”.");
                return [sText, nCount];
            }
            for (let [zRgx, sRep] of oReplTable[sOptName]) {
                nCount += (sText.match(zRgx) || []).length;
                sText = sText.replace(zRgx, sRep);
            }
        }
        catch (e) {
            console.error(e);
        }
        return [sText, nCount];
    }
}


/* EVENTS */

window.addEventListener("load", function (xEvent) {
    oGrammarChecker.loadGC();
    //oGrammarChecker.fullTests();
}, false);

window.addEventListener("compose-window-init", function (xEvent) {
    oGrammarChecker.loadUI();
    oGrammarChecker.closePanel();
    oGrammarChecker.clearPreview();
    oTextFormatter.init();
}, true);

Deleted gc_lang/fr/mailext/content/overlay.xul version [c9ae1732ec].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

























































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://grammarchecker/content/overlay.css" type="text/css"?>
<!--<?xml-stylesheet type="text/css" href="chrome://messenger/skin/messenger.css"?>-->

<!DOCTYPE overlay SYSTEM "chrome://grammarchecker/locale/overlay.dtd">

<overlay id="grammarchecker-overlay"
         xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
  <script type="application/javascript" src="chrome://messenger/content/customElements.js"/>
  <script type="application/javascript" src="resource://grammalecte/text.js"/>
  <script type="application/javascript" src="resource://grammalecte/fr/textformatter.js"/>
  <script type="application/javascript" src="overlay.js"/>
  <script type="application/javascript" src="file_handler.js"/>
  <script type="application/javascript" src="spellchecker.js"/>
  <script type="application/javascript" src="editor.js"/>


  <!--<stringbundleset id="stringbundleset">
    <stringbundle id="grammarchecker-strings" src="chrome://grammarchecker/locale/grammarchecker.properties"/>
  </stringbundleset>-->

  <commandset id="composerEditMenuItems" commandupdater="true"
              events="focus"
              oncommandupdate="goUpdateCommand('cmd_grammar')">
    <command id="cmd_grammar" label="&grammarchecker.button.label;" oncommand="goDoCommand('cmd_grammar')"/>
  </commandset>

  <menupopup id="taskPopup">
    <!-- menu tools -->
    <menuitem id="grammarchecker-hello" command="cmd_grammar"/>
  </menupopup>

  <popup id="msgComposeContext">
    <!-- contextual menu -->
    <menuitem id="context-grammarchecker" command="cmd_grammar"
        accesskey="&grammarchecker.accesskey;"/>
  </popup>

  <toolbarpalette id="MsgComposeToolbarPalette">
    <!-- toolbar palette -->
    <toolbarbutton id="grammarchecker-toolbar-button" command="cmd_grammar"
                   tooltiptext="&grammarchecker.tooltip;"
                   class="toolbarbutton-1 chromeclass-toolbar-additional" />

    <toolbarbutton id="grammalecte-menu" type="menu-button" label="Grammalecte" class="toolbarbutton-1" tooltip="&grammarchecker.tooltip;" oncommand="">
      <menupopup id="gl-toolbar-popup">
        <menuitem id="gl-item-conj" class="menuitem-iconic" label="&grammalectemenu.textformatter;" oncommand="oTextFormatter.onOpenPanel(event);"/>
        <menuitem id="gl-item-conj" class="menuitem-iconic" label="&grammalectemenu.conjugueur;" oncommand="oGrammarChecker.onOpenConjugueur(event);"/>
        <menuseparator/>
        <menuitem id="gl-item-analyze" class="menuitem-iconic" label="&grammalectemenu.start;" oncommand="oGrammarChecker.onParseText(event);"/>
        <menuitem id="gl-item-options" class="menuitem-iconic" label="&grammalectemenu.gc_options;" onclick="oGrammarChecker.onOpenGCOptions(event);"/>
        <menuitem id="gl-item-options" class="menuitem-iconic" label="&grammalectemenu.spell_options;" onclick="oGrammarChecker.onOpenSpellOptions(event);"/>
        <menuitem id="gl-item-options" class="menuitem-iconic" label="&grammalectemenu.other_options;" onclick="oGrammarChecker.onOpenOptions(event);"/>
        <menuitem id="gl-item-options" class="menuitem-iconic" label="&grammalectemenu.lexicon_editor;" onclick="oGrammarChecker.onOpenLexiconEditor(event);"/>
        <menuseparator/>
        <menuitem id="gl-item-about" class="menuitem-iconic" label="&grammalectemenu.about;" oncommand="oGrammarChecker.onAbout(event);"/>
      </menupopup>
    </toolbarbutton>
  </toolbarpalette>


  <vbox id="appcontent">

    <!--

      TEXT FORMATTER PANEL

    -->
    <splitter id="textformatter-splitter" state="collapsed" collapse="after"><grippy /></splitter>

    <vbox id="textformatter-panel">

      <div class="dialogheader-title">Grammalecte · &textformatter; · &automated_replacements;</div>

      <hbox id="tf-columns">
        <vbox class="column" width="400">
          <!-- Supernumerary spaces -->
          <groupbox>
            <hbox class="groupbox-title">
              <label class="header"><checkbox id="o_group_ssp" class="option optiongroup" data-default="true" label="&tf_ssp;" /></label>
            </hbox>
            <vbox id="group_ssp" class="groupblock">
              <hbox class="blockopt underline">
                <checkbox id="o_start_of_paragraph" class="option" data-default="true" label="&tf_start_of_paragraph;" />
                <spacer flex="1" />
                <label id="res_o_start_of_paragraph" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_end_of_paragraph" class="option" data-default="true" label="&tf_end_of_paragraph;" />
                <spacer flex="1" />
                <label id="res_o_end_of_paragraph" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_between_words" class="option" data-default="true" label="&tf_between_words;" />
                <spacer flex="1" />
                <label id="res_o_between_words" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_before_punctuation" class="option" data-default="true" label="&tf_before_punctuation;" />
                <spacer flex="1" />
                <label id="res_o_before_punctuation" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_within_parenthesis" class="option" data-default="true" label="&tf_within_parenthesis;" />
                <spacer flex="1" />
                <label id="res_o_within_parenthesis" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_within_square_brackets" class="option" data-default="true" label="&tf_within_square_brackets;" />
                <spacer flex="1" />
                <label id="res_o_within_square_brackets" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_within_quotation_marks" class="option" data-default="true" label="&tf_within_quotation_marks;" />
                <spacer flex="1" />
                <label id="res_o_within_quotation_marks" class="result" />
              </hbox>
            </vbox>
          </groupbox>

          <!-- Missing spaces -->
          <groupbox>
            <hbox class="groupbox-title">
              <label class="header"><checkbox id="o_group_space" class="option optiongroup" data-default="true" label="&tf_space;" /></label>
            </hbox>
            <vbox id="group_space" class="groupblock">
              <hbox class="blockopt underline">
                <checkbox id="o_add_space_after_punctuation" class="option" data-default="true" label="&tf_add_space_after_punctuation;" />
                <spacer flex="1" />
                <label id="res_o_add_space_after_punctuation" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_add_space_around_hyphens" class="option" data-default="true" label="&tf_add_space_around_hyphens;" />
                <spacer flex="1" />
                <label id="res_o_add_space_around_hyphens" class="result" />
              </hbox>
            </vbox>
          </groupbox>

          <!-- Non breaking spaces -->
          <groupbox>
            <hbox class="groupbox-title">
              <label class="header"><checkbox id="o_group_nbsp" class="option optiongroup" data-default="true" label="&tf_nbsp;" /></label>
            </hbox>
            <vbox id="group_nbsp" class="groupblock">
              <hbox class="blockopt underline">
                <checkbox id="o_nbsp_before_punctuation" class="option" data-default="true" label="&tf_nbsp_before_punctuation;" />
                <!--<div class="secondoption">
                  <checkbox id="o_nnbsp_before_punctuation" class="option" />
                  <label="o_nnbsp_before_punctuation" class="opt_lbl smallw">fines<span>sauf avec “:”</span></label>
                </div>-->
                <spacer flex="1" />
                <label id="res_o_nbsp_before_punctuation" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_nbsp_within_quotation_marks" class="option" data-default="true" label="&tf_nbsp_within_quotation_marks;" />
                <!--<div class="secondoption">
                  <checkbox id="o_nnbsp_within_quotation_marks" class="option" />
                  <label="o_nnbsp_within_quotation_marks" class="opt_lbl smallw">fines</label>
                </div>-->
                <spacer flex="1" />
                <label id="res_o_nbsp_within_quotation_marks" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                  <checkbox id="o_nbsp_before_symbol" class="option" data-default="true" label="&tf_nbsp_before_symbol;" />
                  <spacer flex="1" />
                  <label id="res_o_nbsp_before_symbol" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_nbsp_within_numbers" class="option" data-default="true" label="&tf_nbsp_within_numbers;" />
                <!--<div class="secondoption">
                  <checkbox id="o_nnbsp_within_numbers" class="option" />
                  <label="o_nnbsp_within_numbers" class="opt_lbl smallw">fines</label>
                </div>-->
                <spacer flex="1" />
                <label id="res_o_nbsp_within_numbers" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_nbsp_before_units" class="option" data-default="true" label="&tf_nbsp_before_units;" />
                <spacer flex="1" />
                <label id="res_o_nbsp_before_units" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_nbsp_titles" class="option" data-default="true" label="&tf_nbsp_titles;" />
                <spacer flex="1" />
                <label id="res_o_nbsp_titles" class="result" />
              </hbox>
            </vbox>
          </groupbox>

          <!-- Deletions -->
          <groupbox>
            <hbox class="groupbox-title">
              <label class="header"><checkbox id="o_group_delete" class="option optiongroup" data-default="true" label="&tf_delete;" /></label>
            </hbox>
            <vbox id="group_delete" class="groupblock">
              <hbox class="blockopt underline">
                <checkbox id="o_erase_non_breaking_hyphens" class="option" data-default="true" label="&tf_erase_non_breaking_hyphens;" />
                <spacer flex="1" />
                <label id="res_o_erase_non_breaking_hyphens" class="result" />
              </hbox>
            </vbox>
          </groupbox>
        </vbox>

        <vbox class="column" width="400">
          <!-- Typographical signs -->
          <groupbox>
            <hbox class="groupbox-title">
              <label class="header"><checkbox id="o_group_typo" class="option optiongroup" data-default="true" label="&tf_typo;" /></label>
            </hbox>
            <vbox id="group_typo" class="groupblock">
              <hbox class="blockopt underline">
                <checkbox id="o_ts_apostrophe" class="option" data-default="true" label="&tf_ts_apostrophe;" />
                <spacer flex="1" />
                <label id="res_o_ts_apostrophe" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_ts_ellipsis" class="option" data-default="true" label="&tf_ts_ellipsis;" />
                <spacer flex="1" />
                <label id="res_o_ts_ellipsis" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_ts_dash_middle" class="option" data-default="true" label="&tf_ts_dash_middle;" />
                <spacer flex="1" />
                <label id="res_o_ts_dash_middle" class="result" />
              </hbox>
              <hbox class="blockopt">
                <spacer flex="1" />
                <radiogroup orient="horizontal">
                  <radio id="o_ts_m_dash_middle" class="option" data-default="false" label="&tf_emdash;" />
                  <radio id="o_ts_n_dash_middle" class="option" data-default="true" label="&tf_endash;" selected="true" />
                </radiogroup>
                <spacer flex="3" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_ts_dash_start" class="option" data-default="true" label="&tf_ts_dash_start;" />
                <spacer flex="1" />
                <label id="res_o_ts_dash_start" class="result" />
              </hbox>
              <hbox class="blockopt">
                <spacer flex="1" />
                <radiogroup orient="horizontal">
                  <radio id="o_ts_m_dash_start" class="option"  data-default="true" label="&tf_emdash;" selected="true" />
                  <radio id="o_ts_n_dash_start" class="option" data-default="false" label="&tf_endash;" />
                </radiogroup>
                <spacer flex="3" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_ts_quotation_marks" class="option" data-default="true" label="&tf_ts_quotation_marks;" />
                <spacer flex="1" />
                <label id="res_o_ts_quotation_marks" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_ts_units" class="option" data-default="true" label="&tf_ts_units;" />
                <spacer flex="1" />
                <label id="res_o_ts_units" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_ts_spell" class="option" data-default="true" label="&tf_ts_spell;" />
                <spacer flex="1" />
                <label id="res_o_ts_spell" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_ts_ligature" class="option" data-default="false" label="&tf_ts_ligature;" />
                <input type="radio" id="o_ts_ligature_do" name="liga" class="option" data-default="false" label="&tf_ts_ligature_do;" />
                <input type="radio" id="o_ts_ligature_undo" name="liga" class="option" data-default="true" label="&tf_ts_ligature_undo;" />
                <spacer flex="1" />
                <label id="res_o_ts_ligature" class="result" />
              </hbox>
              <hbox class="blockopt">
                <spacer flex="1" />
                <checkbox id="o_ts_ligature_ff" class="option" data-default="true" label="ff" />
                <checkbox id="o_ts_ligature_fi" class="option" data-default="true" label="fi" />
                <checkbox id="o_ts_ligature_ffi" class="option" data-default="true" label="ffi" />
                <checkbox id="o_ts_ligature_fl" class="option" data-default="true" label="fl" />
                <checkbox id="o_ts_ligature_ffl" class="option" data-default="true" label="ffl" />
                <checkbox id="o_ts_ligature_ft" class="option" data-default="true" label="ft" />
                <checkbox id="o_ts_ligature_st" class="option" data-default="false" label="st" />
                <spacer flex="2" />
              </hbox>
            </vbox>
          </groupbox>

          <!-- Misc -->
          <groupbox>
            <hbox class="groupbox-title">
              <label class="header"><checkbox id="o_group_misc" class="option optiongroup" data-default="true" label="&tf_misc;" /></label>
            </hbox>
            <vbox id="group_misc" class="groupblock">
              <hbox class="blockopt underline">
                <checkbox id="o_ordinals_no_exponant" class="option" data-default="true" label="&tf_ordinals_no_exponant;" />
                <checkbox id="o_ordinals_exponant" class="option" data-default="true" label="&tf_ordinals_exponant;" />
                <spacer flex="1" />
                <label id="res_o_ordinals_no_exponant" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_etc" class="option" data-default="true" label="&tf_etc;" />
                <spacer flex="1" />
                <label id="res_o_etc" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_missing_hyphens" class="option" data-default="true" label="&tf_missing_hyphens;" />
                <spacer flex="1" />
                <label id="res_o_missing_hyphens" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_ma_word" class="option" data-default="true" label="&tf_ma_word;" />
                <spacer flex="1" />
                <label id="res_o_ma_word" class="result" />
              </hbox>
              <hbox class="blockopt">
                <spacer flex="1" />
                <checkbox id="o_ma_1letter_lowercase" class="option" label="&tf_ma_1letter_lowercase;" />
                <checkbox id="o_ma_1letter_uppercase" class="option" label="&tf_ma_1letter_uppercase;" />
                <spacer flex="3" />
              </hbox>
            </vbox>
          </groupbox>

          <!-- Restructuration -->
          <!--<groupbox>
            <hbox class="groupbox-title">
              <label class="header"><checkbox id="o_group_struct" class="option optiongroup" data-default="false" label="&tf_struct;" /></label>
            </hbox>
            <vbox id="group_struct" class="groupblock">
              <hbox class="blockopt underline">
                <checkbox id="o_remove_hyphens_at_end_of_paragraphs" class="option" data-default="false" label="&tf_remove_hyphens_at_end_of_paragraphs;" />
                <spacer flex="1" />
                <label id="res_o_remove_hyphens_at_end_of_paragraphs" class="result" />
              </hbox>
              <hbox class="blockopt underline">
                <checkbox id="o_merge_contiguous_paragraphs" class="option" data-default="false" label="&tf_merge_contiguous_paragraphs;" />
                <spacer flex="1" />
                <label id="res_o_merge_contiguous_paragraphs" class="result" />
              </hbox>
            </vbox>
          </groupbox>-->

          <description id="textformatter-infomsg">&tf_infomsg;</description>
        </vbox>
      </hbox>

      <hbox id="textformatter-commands">
        <button id="reset" label="&tf.button.default;" oncommand="oTextFormatter.onReset(event);" />
        <html:progress id="textformatter-progressbar" max="6"></html:progress>
        <label id="textformatter-timer" width="50"></label>
        <button id="apply" label="&tf.button.apply;" oncommand="oTextFormatter.onApply(event);" />
        <button id="close" label="&tf.button.close;" oncommand="oTextFormatter.onClosePanel(event);" />
      </hbox>

    </vbox>


    <!--

      GRAMMAR CHECKING PANEL

    -->
    <splitter id="grammarchecker-splitter" state="collapsed" collapse="after"><grippy /></splitter>

    <vbox id="grammarchecker-panel">
      <div class="dialogheader-title">Grammalecte · &detected_mistakes;</div>
      <div id="grammalecte-errors"/>
      <hbox id="grammalecte-infobox">
        <label id="grammalecte-info" />
        <spacer flex="1" />
        <label id="closebutton" value="Fermer" onclick="oGrammarChecker.onClosePanel(event);" />
      </hbox>
    </vbox>

  </vbox>

</overlay>

Deleted gc_lang/fr/mailext/content/spell_options.css version [377d800f5a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46














































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/* CSS */

#grouptitle {
    font-size: 16px;
    font-weight: bold;
    color: hsl(0, 50%, 50%);
}

.option {
    font-size: 16px;
    font-weight: bold;
    color: hsl(210, 50%, 50%);
}

.suboption {
    margin-left: 30px;
    font-size: 16px;
    font-weight: bold;
    color: hsl(210, 50%, 50%);
}
.suboption2 {
    margin-left: 30px;
}

description {
    width: 340px;
}

.dicdescr {
      margin-left: 27px;
}

.disabled {
    opacity: .25;
}


.dialogheader-title {
    margin: 5px;
    padding: 5px 8px;
    border: 1px solid hsl(210, 50%, 80%);
    background-color: hsl(210, 50%, 50%);
    color: hsl(210, 10%, 90%);
    font-size: larger;
    font-weight: bold;
}

Deleted gc_lang/fr/mailext/content/spell_options.js version [d5cdd1e710].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76












































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// JavaScript

"use strict";


const Cc = Components.classes;
const Ci = Components.interfaces;
// const Cu = Components.utils;
const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");


var oDialogControl = {
    load: function () {
        try {
            // center window
            document.getElementById('grammalecte-spelloptions-window').centerWindowOnScreen();
            // main spelling dictionary
            let sMainDicName = prefs.getCharPref('sMainDicName');
            console.log("spelling dictionary:", sMainDicName);
            if (sMainDicName == "fr-classic.json") {
                document.getElementById("classic").checked = true;
            }
            else if (sMainDicName == "fr-reform.json") {
                document.getElementById("reform").checked = true;
            }
            else if (sMainDicName == "fr-allvars.json") {
                document.getElementById("allvars").checked = true;
            }
            // personal dictionary
            document.getElementById('personal_dic').checked = prefs.getBoolPref('bPersonalDictionary');
            // listen
            this.listen();
        }
        catch (e) {
            console.error(e);
        }
    },
    listen: function () {
        document.addEventListener("dialogaccept", (event) => {
            oDialogControl.setDictionaries();
        });
        document.getElementById("classic").addEventListener("click", (event) => {
            oDialogControl.changeMainDicUI("classic");
        });
        document.getElementById("reform").addEventListener("click", (event) => {
            oDialogControl.changeMainDicUI("reform");
        });
        document.getElementById("allvars").addEventListener("click", (event) => {
            oDialogControl.changeMainDicUI("allvars");
        });
    },
    changeMainDicUI (sDic) {
        document.getElementById("classic").checked = ("classic" === sDic);
        document.getElementById("reform").checked = ("reform" === sDic);
        document.getElementById("allvars").checked = ("allvars" === sDic);
    },
    setDictionaries: function () {
        //oSpellControl.init();
        // main spelling dictionary
        let sMainDicName = "";
        if (document.getElementById("classic").checked) {
            sMainDicName = "fr-classic.json";
        }
        else if (document.getElementById("reform").checked) {
            sMainDicName = "fr-reform.json";
        }
        else if (document.getElementById("allvars").checked) {
            sMainDicName = "fr-allvars.json";
        }
        console.log("selected spelling dictionary:", sMainDicName);
        prefs.setCharPref("sMainDicName", sMainDicName);
        // personal dictionary
        let bActivate = document.getElementById('personal_dic').checked;
        prefs.setBoolPref("bPersonalDictionary", bActivate);
    }
};

Deleted gc_lang/fr/mailext/content/spell_options.xul version [abb535b915].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67



































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://grammarchecker/content/spell_options.css" type="text/css"?>

<!DOCTYPE dialog SYSTEM "chrome://grammarchecker/locale/spell_options.dtd">

<dialog
  id="grammalecte-spelloptions-window"
  title="&window.title;"
  orient="vertical"
  buttons="accept,cancel"
  width="400"
  height="330"
  onload="oDialogControl.load();"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <!-- Other elements go here -->

  <div class="dialogheader-title">&dialogheader.label;</div>

  <hbox>
    <!--
    <groupbox with="380">
      <caption id="grouptitle" label="&grouptitle_hunspell;" />
      <description id="warning">&warning_hunspell;</description>

      <checkbox id="fr-FR-modern" class="option" label="&option.modern.label;" />
      <description class="dicdescr">&option.modern.descr;</description>
      <checkbox id="fr-FR-classic" class="option" label="&option.classic.label;" />
      <description class="dicdescr">&option.classic.descr;</description>
      <checkbox id="fr-FR-reform" class="option" label="&option.reform.label;" />
      <description class="dicdescr">&option.reform.descr;</description>
      <checkbox id="fr-FR-classic-reform" class="option" label="&option.allvar.label;" />
      <description class="dicdescr">&option.allvar.descr;</description>
    </groupbox>
    -->

    <groupbox with="380">
      <caption id="grouptitle" label="&grouptitle_graphspell;" />
      <description id="warning">&warning_graphspell;</description>

      <checkbox id="main_dic" class="option" label="&option.main_dic.label;" disabled="true" checked="true" />
      <description class="dicdescr">&option.main_dic.descr;</description>
      <label class="suboption" value="&option.main_dic.spelling;" />
      <hbox class="suboption2" >
        <checkbox id="classic" label="&option.main_dic.classic;" checked="false" />
        <checkbox id="reform" label="&option.main_dic.reform;" checked="false" />
        <checkbox id="allvars" label="&option.main_dic.allvars;" checked="false" />
      </hbox>
      <!--<radiogroup id="main_dic_name" class="suboption2" orient="horizontal">
        <radio id="classic" label="&option.main_dic.classic;" value="fr-classic.json" />
        <radio id="reform" label="&option.main_dic.reform;" value="fr-reform.json" />
        <radio id="allvars" label="&option.main_dic.allvars;" value="fr-allvars.json" />
      </radiogroup>-->

      <checkbox id="community_dic" class="option disabled" label="&option.community_dic.label;" disabled="true" />
      <description class="dicdescr disabled">&option.community_dic.descr;</description>

      <checkbox id="personal_dic" class="option" label="&option.personal_dic.label;" />
      <description class="dicdescr">&option.personal_dic.descr;</description>
    </groupbox>
  </hbox>

  <script type="application/javascript" src="spell_options.js"/>
  <script type="application/javascript" src="spellchecker.js"/>

</dialog>

Deleted gc_lang/fr/mailext/content/spellchecker.js version [ca575ac13b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
















































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// JavaScript

/*
    Hunspell wrapper

    XPCOM obsolete (?), but there is nothing else...
    Overly complicated and weird. To throw away ASAP if possible.

    And you can’t access to this from a PromiseWorker (it sucks).

    https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/mozISpellCheckingEngine
    https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Using_spell_checking_in_XUL
    https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFile
    https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/FileUtils.jsm
*/

"use strict";


const { FileUtils } = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
const { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");


var oSpellControl = {
    xSCEngine: null,
    init: function () {
        if (this.xSCEngine === null) {
            try {
                let sSpellchecker = "@mozilla.org/spellchecker/myspell;1";
                if ("@mozilla.org/spellchecker/hunspell;1" in Cc) {
                    sSpellchecker = "@mozilla.org/spellchecker/hunspell;1";
                }
                if ("@mozilla.org/spellchecker/engine;1" in Cc) {
                    sSpellchecker = "@mozilla.org/spellchecker/engine;1";
                }
                this.xSCEngine = Cc[sSpellchecker].getService(Ci.mozISpellCheckingEngine);
            }
            catch (e) {
                console.log("Can’t initiate the spellchecker.");
                console.error(e);
            }
        }
    },
    getDictionariesList: function () {
        this.init();
        try {
            let l = {};
            let c = {};
            this.xSCEngine.getDictionaryList(l, c);
            return l.value;
        }
        catch (e) {
            console.error(e);
            return [];
        }
    },
    setDictionary: function (sLocale) {
        if (this.getDictionariesList().includes(sLocale)) {
            try {
                this.xSCEngine.dictionary = sLocale; // en-US, fr, etc.
                return true;
            }
            catch (e) {
                console.error(e);
                return false;
            }
        } else {
            console.log("Warning. No dictionary for locale: " + sLocale);
            console.log("Existing dictionaries: " + this.getDictionariesList().join(" | "));
        }
        return false;
    },
    check: function (sWord) {
        // todo: check in personal dict?
        try {
            return this.xSCEngine.check(sWord);
        }
        catch (e) {
            console.error(e);
            return false;
        }
    },
    suggest: function (sWord) {
        try {
            let lSugg = {};
            this.xSCEngine.suggest(sWord, lSugg, {});
            return lSugg.value;
            // lSugg.value is a JavaScript Array of strings
        }
        catch (e) {
            console.error(e);
            return ['#Erreur.'];
        }
    },
    addDirectory: function (sFolder) {
        try {
            let xNsiFolder = new FileUtils.File(sFolder);
            this.xSCEngine.addDirectory(xNsiFolder);
        }
        catch (e) {
            console.log("Unable to add directory: " + sFolder);
            console.error(e);
        }
    },
    removeDirectory: function (sFolder) {
        // does not work but no exception raised (bug?)
        try {
            let xNsiFolder = new FileUtils.File(sFolder);
            this.xSCEngine.removeDirectory(xNsiFolder);
        }
        catch (e) {
            console.log("Unable to remove directory: " + sFolder);
            console.error(e);
        }
    },
    setExtensionDictFolder: function (sDictName, bActivate) {
        try {
            let that = this;
            let sPath = "/content/dictionaries/" + sDictName;
            AddonManager.getAddonByID("French-GC-TB@grammalecte.net")
            .then(function (xAddon) {
                let xURI = xAddon.getResourceURI(sPath);
                //console.log(xURI);
                let sFolder = xURI.filePath;
                if (sFolder !== undefined) {
                    if (/^\/[A-Z]:\//.test(sFolder)) {
                        // Windows path
                        sFolder = sFolder.slice(1).replace(/\//g, "\\\\");
                    }
                    console.log("folder: " + sFolder);
                    if (bActivate) {
                        that.addDirectory(sFolder);
                    } else {
                        that.removeDirectory(sFolder);
                    }
                }
            });
        }
        catch (e) {
            console.log("Unable to add extension folder");
            console.error(e);
        }
    }
};

Deleted gc_lang/fr/mailext/defaults/preferences/grammarchecker.js version [8769787af8].

1
2
3
4
5
6
7
8
9
10










-
-
-
-
-
-
-
-
-
-
pref("extensions.grammarchecker.sGCOptions", "");
pref("extensions.grammarchecker.sTFOptions", "");
pref("extensions.grammarchecker.bDictModern", false);
pref("extensions.grammarchecker.bDictClassic", true);
pref("extensions.grammarchecker.bDictReform", false);
pref("extensions.grammarchecker.bDictClassicReform", false);
pref("extensions.grammarchecker.bCheckSignature", true);
pref("extensions.grammarchecker.sMainDicName", "fr-allvars.json");
pref("extensions.grammarchecker.bCommunityDictionary", false);
pref("extensions.grammarchecker.bPersonalDictionary", true);

Deleted gc_lang/fr/mailext/locale/en/about.dtd version [586b114cab].

1
2
3
4
5
6
7







-
-
-
-
-
-
-
<!ENTITY windowtitle "About Grammalecte">
<!ENTITY description1 "French">
<!ENTITY description2 "Grammar Checker">
<!ENTITY version "Version:">
<!ENTITY license "License:">
<!ENTITY thanks "Thanks to">
<!ENTITY contrib "and those who supported us…">

Deleted gc_lang/fr/mailext/locale/en/gc_options.dtd version [6feaf76b9e].

1
2
3
4




-
-
-
-
<!ENTITY window.title "Grammalecte · Grammar options">
<!ENTITY defaultbutton.label "Default">
<!ENTITY dialogheader.label "Grammar options">
${gc_options_labels_en}

Deleted gc_lang/fr/mailext/locale/en/grammarchecker.properties version [ef0da976ea].

1
2
3



-
-
-
processingMessage=Parsing in progress…
errorMessage=Error…
noErrorMessage=No error detected.

Deleted gc_lang/fr/mailext/locale/en/lex_editor.dtd version [d8b06fdebc].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<!ENTITY window.title "Grammalecte · Lexical editor lexical">

<!ENTITY button.cancel.label "Close">

<!ENTITY tab.editor.label "Add">
<!ENTITY tab.lexicon.label "Lexicon">
<!ENTITY tab.search.label "Search">
<!ENTITY tab.info.label "Informations">

<!ENTITY dialogheader.newword.label "New word (lemma)">
<!ENTITY dialogheader.generated_words.label "Generated words">
<!ENTITY dialogheader.lexicon.label "Your lexicon">
<!ENTITY dialogheader.search.similar.label "Similar spellings">
<!ENTITY dialogheader.search.regex.label "Regular expressions">
<!ENTITY dialogheader.search.result.label "Result">
<!ENTITY dialogheader.info.label "Informations">
<!ENTITY dialogheader.tags.label "Meaning of tags">

Deleted gc_lang/fr/mailext/locale/en/options.dtd version [5fe56718ba].

1
2
3
4
5
6






-
-
-
-
-
-
<!ENTITY window.title "Grammalecte · Options">
<!ENTITY dialogheader.label "Other options">
<!ENTITY check_signature.label "Check signature text (in text mode)">
<!ENTITY check_signature.accesskey "C">


Deleted gc_lang/fr/mailext/locale/en/overlay.dtd version [1e54ceb89b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70






































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<!ENTITY grammarchecker.button.label "Grammar">
<!ENTITY grammarchecker.accesskey "G">
<!ENTITY grammarchecker.tooltip "Grammar checking">

<!ENTITY grammalectemenu.textformatter "Text formatter…">
<!ENTITY grammalectemenu.conjugueur "Conjugation tool…">
<!ENTITY grammalectemenu.start "Proofread the text…">
<!ENTITY grammalectemenu.spell_options "Spelling options…">
<!ENTITY grammalectemenu.gc_options "Grammar options…">
<!ENTITY grammalectemenu.lexicon_editor "Lexical editor…">
<!ENTITY grammalectemenu.other_options "Other options…">
<!ENTITY grammalectemenu.about "About Grammalecte…">

<!ENTITY detected_mistakes "Detected mistakes">

<!ENTITY textformatter "Text Formatter">
<!ENTITY automated_replacements "Automated replacements">
<!ENTITY tf.button.default "Default">
<!ENTITY tf.button.apply "Apply">
<!ENTITY tf.button.close "Close">

<!ENTITY tf_title "Text Formatter">
<!ENTITY tf_ssp "Supernumerary spaces">
<!ENTITY tf_start_of_paragraph "At the beginning of paragraph">
<!ENTITY tf_between_words "Between words">
<!ENTITY tf_end_of_paragraph "At the end of paragraph">
<!ENTITY tf_before_punctuation "Before dots (.), commas (,)">
<!ENTITY tf_within_parenthesis "Within parenthesis">
<!ENTITY tf_within_square_brackets "Within square brackets">
<!ENTITY tf_within_quotation_marks "Within “ and ”">
<!ENTITY tf_space "Missing spaces">
<!ENTITY tf_add_space_after_punctuation "After , ; : ? ! . …">
<!ENTITY tf_add_space_around_hyphens "Surrounding dashes">
<!ENTITY tf_nbsp "Non breaking spaces">
<!ENTITY tf_nbsp_before_punctuation "Before : ; ? and !">
<!ENTITY tf_nbsp_within_quotation_marks "With quoting marks « and »">
<!ENTITY tf_nbsp_before_symbol "Before &#x0025; ‰ € $ £ ¥ ˚C">
<!ENTITY tf_nbsp_within_numbers "Within numbers">
<!ENTITY tf_nbsp_before_units "Before units of measurement">
<!ENTITY tf_nbsp_titles "After titles">
<!ENTITY tf_delete "Deletions">
<!ENTITY tf_erase_non_breaking_hyphens "Soft hyphens">
<!ENTITY tf_typo "Typographical signs">
<!ENTITY tf_ts_apostrophe "Apostrophe (’)">
<!ENTITY tf_ts_ellipsis "Ellipsis (…)">
<!ENTITY tf_ts_dash_middle "Dashes:">
<!ENTITY tf_ts_dash_start "Dashes at beginning of paragraph:">
<!ENTITY tf_emdash "em dash (—)">
<!ENTITY tf_endash "en dash (–)">
<!ENTITY tf_ts_quotation_marks "Change quotation marks  (&quot; and ')">
<!ENTITY tf_ts_units "Interpuncts in units (N·m, Ω·m…)">
<!ENTITY tf_ts_spell "Ligatures (cœur…) and diacritics (ça, État…)">
<!ENTITY tf_ts_ligature "Ligatures">
<!ENTITY tf_ts_ligature_do "Set">
<!ENTITY tf_ts_ligature_undo "Unset">
<!ENTITY tf_misc "Miscellaneous">
<!ENTITY tf_ordinals_no_exponant "Ordinals (15e, XXIe…)">
<!ENTITY tf_ordinals_exponant "e → ᵉ">
<!ENTITY tf_etc "Et cætera, etc.">
<!ENTITY tf_missing_hyphens "Missing hyphens">
<!ENTITY tf_ma_word "Missing apostrophes">
<!ENTITY tf_ma_1letter_lowercase "single letters (j’ n’ m’ t’ s’ c’ d’ l’)">
<!ENTITY tf_ma_1letter_uppercase "Cap.">
<!ENTITY tf_struct "Restructuration [!]">
<!ENTITY tf_remove_hyphens_at_end_of_paragraphs "Remove syllabification hyphens at EOL/EOP">
<!ENTITY tf_merge_contiguous_paragraphs "Merge contiguous paragraphs [!]">
<!ENTITY tf_apply "Apply">
<!ENTITY tf_default "Default">
<!ENTITY tf_close "Close">
<!ENTITY tf_infomsg "The text formatter is a tool which automates correction of typographical errors. Use this tool with caution. Check your text after use. If you write in HTML mode, the use of this module is at your own risk.">

Deleted gc_lang/fr/mailext/locale/en/spell_options.dtd version [fc8174b93b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28




























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<!ENTITY window.title "Grammalecte · Spelling options">
<!ENTITY dialogheader.label "Spelling options">

<!ENTITY grouptitle_graphspell "Graphspell Dictionaries (Grammalecte)">
<!ENTITY warning_graphspell "These dictionaries are used only when analyzing texts.">
<!ENTITY option.main_dic.label "Main dictionary">
<!ENTITY option.main_dic.descr "About 83 000 entries, 500 000 flexions. Not editable, not deactivable.">
<!ENTITY option.main_dic.spelling "Spelling">
<!ENTITY option.main_dic.classic "Classic">
<!ENTITY option.main_dic.reform "Reform 1990">
<!ENTITY option.main_dic.allvars "All variants">
<!ENTITY option.community_dic.label "Community dictionary">
<!ENTITY option.community_dic.descr "Feature to come..">
<!ENTITY option.personal_dic.label "Personal dictionary">
<!ENTITY option.personal_dic.descr "The personal dictionary is created and edited via the lexicon editor.">

<!ENTITY grouptitle_hunspell "Hunspell Dictionaries (Thunderbird)">
<!ENTITY warning_hunspell "These dictionaries are only used when you are writing texts (red underlining). Select dictionaries you want to see in textareas list. Selected dictionaries are added instantly. Whereas unselected dictionnaries will be removed only at Thunderbird’s restart.">
<!ENTITY option.modern.label "“Modern”">
<!ENTITY option.modern.descr "This dictionary offers the French spelling as it is written nowadays most often. This is the recommended dictionary if French is not your mother tongue or if you want only one correct spelling per word.">
<!ENTITY option.classic.label "“Classic” (recommanded)">
<!ENTITY option.classic.descr "This is the “Modern” dictionary plus classical spellings, some of them still widely used, others obsolete. This is the recommended dictionary if French is your native language.">
<!ENTITY option.reform.label "“Reform 1990”">
<!ENTITY option.reform.descr "With this dictionary, only the reformed spelling is recognized. As many of reformed spellings are considered erroneous for many people, this dictionary is unadvised. Reformed spellings commonly used are already included in the “Modern” dictionary.">
<!ENTITY option.allvar.label "“All variants”">
<!ENTITY option.allvar.descr "This dictionary contains all spelling variants, classical and reformed, and some others even rarer. This dictionary is unadvised for those who don’t know very well the French language.">


Deleted gc_lang/fr/mailext/locale/fr/about.dtd version [4705e2f2e0].

1
2
3
4
5
6
7







-
-
-
-
-
-
-
<!ENTITY windowtitle "À propos de Grammalecte">
<!ENTITY description1 "Correcteur grammatical">
<!ENTITY description2 "pour le français">
<!ENTITY version "Version :">
<!ENTITY license "Licence :">
<!ENTITY thanks "Avec le soutien de">
<!ENTITY contrib "et de nombreux contributeurs…">

Deleted gc_lang/fr/mailext/locale/fr/gc_options.dtd version [aa14ca951b].

1
2
3
4




-
-
-
-
<!ENTITY window.title "Grammalecte · Options grammaticales">
<!ENTITY defaultbutton.label "Par défaut">
<!ENTITY dialogheader.label "Options grammaticales">
${gc_options_labels_fr}

Deleted gc_lang/fr/mailext/locale/fr/grammarchecker.properties version [e42689d6bb].

1
2
3



-
-
-
processingMessage=Analyse en cours
errorMessage=Erreur…
noErrorMessage=Aucune erreur détectée.

Deleted gc_lang/fr/mailext/locale/fr/lex_editor.dtd version [6b48b9e817].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<!ENTITY window.title "Grammalecte · Éditeur lexical">

<!ENTITY button.cancel.label "Fermer">

<!ENTITY tab.editor.label "Ajout">
<!ENTITY tab.lexicon.label "Lexique">
<!ENTITY tab.search.label "Recherche">
<!ENTITY tab.info.label "Informations">

<!ENTITY dialogheader.newword.label "Nouveau mot (lemme)">
<!ENTITY dialogheader.generated_words.label "Mots générés">
<!ENTITY dialogheader.lexicon.label "Votre lexique">
<!ENTITY dialogheader.search.similar.label "Graphies similaires">
<!ENTITY dialogheader.search.regex.label "Expressions régulières">
<!ENTITY dialogheader.search.result.label "Résultat">
<!ENTITY dialogheader.info.label "Informations">
<!ENTITY dialogheader.tags.label "Signification des étiquettes">

Deleted gc_lang/fr/mailext/locale/fr/options.dtd version [37a043f079].

1
2
3
4




-
-
-
-
<!ENTITY window.title "Grammalecte · Options">
<!ENTITY dialogheader.label "Autres options">
<!ENTITY check_signature.label "Vérifier le texte de la signature (en mode texte)">
<!ENTITY check_signature.accesskey "V">

Deleted gc_lang/fr/mailext/locale/fr/overlay.dtd version [93a8ef80c4].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70






































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<!ENTITY grammarchecker.button.label "Grammaire">
<!ENTITY grammarchecker.accesskey "G">
<!ENTITY grammarchecker.tooltip "Correction grammaticale">

<!ENTITY grammalectemenu.textformatter "Formateur de texte…">
<!ENTITY grammalectemenu.conjugueur "Conjugueur…">
<!ENTITY grammalectemenu.start "Analyser le texte…">
<!ENTITY grammalectemenu.spell_options "Options orthographiques…">
<!ENTITY grammalectemenu.gc_options "Options grammaticales…">
<!ENTITY grammalectemenu.lexicon_editor "Éditeur lexical…">
<!ENTITY grammalectemenu.other_options "Autres options…">
<!ENTITY grammalectemenu.about "À propos de Grammalecte…">

<!ENTITY detected_mistakes "Erreurs détectées">

<!ENTITY textformatter "Formateur de texte">
<!ENTITY automated_replacements "Remplacements automatisés">
<!ENTITY tf.button.default "Par défaut">
<!ENTITY tf.button.apply "Appliquer">
<!ENTITY tf.button.close "Fermer">

<!ENTITY tf_title "Formateur de texte">
<!ENTITY tf_ssp "Espaces surnuméraires">
<!ENTITY tf_start_of_paragraph "En début de paragraphe">
<!ENTITY tf_between_words "Entre les mots">
<!ENTITY tf_end_of_paragraph "En fin de paragraphe">
<!ENTITY tf_before_punctuation "Avant les points (.), les virgules (,)">
<!ENTITY tf_within_parenthesis "À l’intérieur des parenthèses">
<!ENTITY tf_within_square_brackets "À l’intérieur des crochets">
<!ENTITY tf_within_quotation_marks "À l’intérieur des guillemets “ et ”">
<!ENTITY tf_space "Espaces manquants">
<!ENTITY tf_add_space_after_punctuation "Après , ; : ? ! . …">
<!ENTITY tf_add_space_around_hyphens "Autour des tirets d’incise">
<!ENTITY tf_nbsp "Espaces insécables">
<!ENTITY tf_nbsp_before_punctuation "Avant : ; ? et !">
<!ENTITY tf_nbsp_within_quotation_marks "Avec les guillemets « et »">
<!ENTITY tf_nbsp_before_symbol "Avant &#x0025; ‰ € $ £ ¥ ˚C">
<!ENTITY tf_nbsp_within_numbers "À l’intérieur des nombres">
<!ENTITY tf_nbsp_before_units "Avant les unités de mesure">
<!ENTITY tf_nbsp_titles "Après les titres de civilité">
<!ENTITY tf_delete "Suppressions">
<!ENTITY tf_erase_non_breaking_hyphens "Tirets conditionnels">
<!ENTITY tf_typo "Signes typographiques">
<!ENTITY tf_ts_apostrophe "Apostrophe (’)">
<!ENTITY tf_ts_ellipsis "Points de suspension (…)">
<!ENTITY tf_ts_dash_middle "Tirets d’incise :">
<!ENTITY tf_ts_dash_start "Tirets en début de paragraphe :">
<!ENTITY tf_emdash "cadratin (—)">
<!ENTITY tf_endash "demi-cadratin (–)">
<!ENTITY tf_ts_quotation_marks "Modifier les guillemets droits (&quot; et ')">
<!ENTITY tf_ts_units "Points médians des unités (N·m, Ω·m…)">
<!ENTITY tf_ts_spell "Ligatures (cœur…) et diacritiques (ça, État…)">
<!ENTITY tf_ts_ligature "Ligatures">
<!ENTITY tf_ts_ligature_do "Faire">
<!ENTITY tf_ts_ligature_undo "Défaire">
<!ENTITY tf_misc "Divers">
<!ENTITY tf_ordinals_no_exponant "Ordinaux (15e, XXIe…)">
<!ENTITY tf_ordinals_exponant "e → ᵉ">
<!ENTITY tf_etc "Et cætera, etc.">
<!ENTITY tf_missing_hyphens "Traits d’union manquants">
<!ENTITY tf_ma_word "Apostrophes manquantes">
<!ENTITY tf_ma_1letter_lowercase "lettres isolées (j’ n’ m’ t’ s’ c’ d’ l’)">
<!ENTITY tf_ma_1letter_uppercase "Maj.">
<!ENTITY tf_struct "Restructuration [!]">
<!ENTITY tf_remove_hyphens_at_end_of_paragraphs "Enlever césures en fin de ligne/paragraphe [!]">
<!ENTITY tf_merge_contiguous_paragraphs "Fusionner les paragraphes contigus [!]">
<!ENTITY tf_apply "Appliquer">
<!ENTITY tf_default "Par défaut">
<!ENTITY tf_close "Fermer">
<!ENTITY tf_infomsg "Le formateur de texte est un outil qui automatise la correction d’erreurs typographiques. Utilisez l’outil avec prudence. Vérifiez votre texte après emploi. Si vous écrivez en mode HTML, l’emploi de ce module est à vos risques et périls.">

Deleted gc_lang/fr/mailext/locale/fr/spell_options.dtd version [5ab4900b2b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26


























-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<!ENTITY window.title "Grammalecte · Options orthographiques">
<!ENTITY dialogheader.label "Options orthographiques">

<!ENTITY grouptitle_graphspell "Dictionnaires de Grammalecte">
<!ENTITY warning_graphspell "Ces dictionnaires ne sont utilisés que lors de l’analyse grammaticale.">
<!ENTITY option.main_dic.label "Dictionnaire principal">
<!ENTITY option.main_dic.descr "Environ 83 000 entrées, 500 000 flexions. Ni éditable, ni désactivable.">
<!ENTITY option.main_dic.spelling "Orthographe">
<!ENTITY option.main_dic.classic "Classique">
<!ENTITY option.main_dic.reform "Réforme 1990">
<!ENTITY option.main_dic.allvars "Toutes variantes">
<!ENTITY option.community_dic.label "Dictionnaire communautaire">
<!ENTITY option.community_dic.descr "Fonctionnalité à venir.">
<!ENTITY option.personal_dic.label "Dictionnaire personnel">
<!ENTITY option.personal_dic.descr "Le dictionnaire personnel est créé et édité via l’éditeur lexical.">

<!ENTITY grouptitle_hunspell "Dictionnaires Hunspell (Thunderbird)">
<!ENTITY warning_hunspell "Ces dictionnaires ne sont utilisés que lors de l’écriture de texte (soulignement rouge). Cochez les dictionnaires que vous voulez voir apparaître dans la liste des dictionnaires utilisables. L’ajout des dictionnaires se fait instantanément. En revanche, les dictionnaires ôtés ne disparaîtront qu’au redémarrage de Thunderbird.">
<!ENTITY option.modern.label "“Moderne”">
<!ENTITY option.modern.descr "Ce dictionnaire propose l’orthographe telle qu’elle est écrite aujourd’hui le plus couramment. C’est le dictionnaire recommandé si le français n’est pas votre langue maternelle ou si vous ne désirez qu’une seule graphie correcte par mot.">
<!ENTITY option.classic.label "“Classique” (recommandé)">
<!ENTITY option.classic.descr "Il s’agit du dictionnaire “Moderne”, avec des graphies classiques en sus, certaines encore communément utilisées, d’autres désuètes. C’est le dictionnaire recommandé si le français est votre langue maternelle.">
<!ENTITY option.reform.label "“Réforme 1990”">
<!ENTITY option.reform.descr "Avec ce dictionnaire, seule l’orthographe réformée est reconnue. Attendu que bon nombre de graphies réformées sont considérées comme erronées par beaucoup, ce dictionnaire est déconseillé. Les graphies passées dans l’usage sont déjà incluses dans le dictionnaire “Moderne”.">
<!ENTITY option.allvar.label "“Toutes variantes”">
<!ENTITY option.allvar.descr "Ce dictionnaire contient les variantes graphiques, classiques, réformées, ainsi que d’autres plus rares encore. Ce dictionnaire est déconseillé à ceux qui ne connaissent pas très bien la langue française.">

Modified gc_lang/fr/mailext/manifest.json from [8fc810be06] to [0e7dd7d210].

11
12
13
14
15
16
17
18
19
20

21
11
12
13
14
15
16
17



18
19







-
-
-
+

  "version": "${version}",

  "author": "${author}",
  "homepage_url": "${link}",



  "legacy":  {
    "type": "xul"
  }

}

Deleted gc_lang/fr/mailext/worker/gce_worker.js version [abd0c9c4ba].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
// JavaScript

// Grammar checker engine
// PromiseWorker
// This code is executed in a separate thread (×20 faster too!!!)

// Firefox WTF: it’s impossible to use require as in the main thread here,
// so it is required to declare a resource in the file “chrome.manifest”.


"use strict";

// copy/paste
// https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/PromiseWorker.jsm

importScripts("resource://gre/modules/workers/require.js");
let PromiseWorker = require("resource://gre/modules/workers/PromiseWorker.js");

// Instantiate AbstractWorker (see below).
let worker = new PromiseWorker.AbstractWorker();

worker.dispatch = function(method, args = []) {
  // Dispatch a call to method `method` with args `args`
  return self[method](...args);
};
worker.postMessage = function(...args) {
  // Post a message to the main thread
  self.postMessage(...args);
};
worker.close = function() {
  // Close the worker
  self.close();
};
worker.log = function(...args) {
  // Log (or discard) messages (optional)
  dump("Worker: " + args.join(" ") + "\n");
};

// Connect it to message port.
self.addEventListener("message", msg => worker.handleMessage(msg));

// end of copy/paste


// no console here, use “dump”

let gce = null; // module: grammar checker engine
let text = null;
let tkz = null; // module: tokenizer
let lxg = null; // module: lexicographer
let helpers = null;

let oTokenizer = null;
let oSpellChecker = null;
let oLxg = null;

function loadGrammarChecker (sGCOptions="", sContext="JavaScript") {
    if (gce === null) {
        try {
            gce = require("resource://grammalecte/fr/gc_engine.js");
            helpers = require("resource://grammalecte/graphspell/helpers.js");
            text = require("resource://grammalecte/text.js");
            tkz = require("resource://grammalecte/graphspell/tokenizer.js");
            //lxg = require("resource://grammalecte/fr/lexicographe.js");
            oTokenizer = new tkz.Tokenizer("fr");
            gce.load(sContext, "sCSS");
            oSpellChecker = gce.getSpellChecker();
            if (sGCOptions !== "") {
                gce.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
            }
            // we always retrieve options from the gce, for setOptions filters obsolete options
            return gce.getOptions().gl_toString();
        }
        catch (e) {
            console.log("# Error: " + e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
        }
    }
}

function setDictionary (sTypeDic, sDictionary) {
    try {
        console.log("set dictionary: " + sTypeDic);
        switch (sTypeDic) {
            case "main":
                oSpellChecker.setMainDictionary(sDictionary);
                break;
            case "community":
                break;
            case "personal":
                let oJSON = JSON.parse(sDictionary);
                oSpellChecker.setPersonalDictionary(oJSON);
                break;
            default:
                console.log("[GCE worker] unknown dictionary type");
        }
    }
    catch (e) {
        console.error(e);
    }
}

function parse (sText, sCountry, bDebug, bContext) {
    let aGrammErr = gce.parse(sText, sCountry, bDebug, bContext);
    return JSON.stringify(aGrammErr);
}

function parseAndSpellcheck (sText, sCountry, bDebug, bContext) {
    let aGrammErr = gce.parse(sText, sCountry, bDebug, null, bContext);
    let aSpellErr = oSpellChecker.parseParagraph(sText);
    return JSON.stringify({ aGrammErr: aGrammErr, aSpellErr: aSpellErr });
}

function suggest (sWord, nSuggLimit=10) {
    let lSugg = []
    for (let aSugg of oSpellChecker.suggest(sWord, nSuggLimit)) {
        lSugg.push(...aSugg);
    }
    return lSugg.join("|");
}

function getOptions () {
    return gce.getOptions().gl_toString();
}

function getDefaultOptions () {
    return gce.getDefaultOptions().gl_toString();
}

function setOptions (sGCOptions) {
    gce.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
    return gce.getOptions().gl_toString();
}

function setOption (sOptName, bValue) {
    gce.setOptions(new Map([ [sOptName, bValue] ]));
    return gce.getOptions().gl_toString();
}

function resetOptions () {
    gce.resetOptions();
    return gce.getOptions().gl_toString();
}

function fullTests (sGCOptions="") {
    if (!gce || !oSpellChecker) {
        return "# Error: grammar checker or dictionary not loaded."
    }
    let dMemoOptions = gce.getOptions();
    if (sGCOptions) {
        gce.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
    }
    let tests = require("resource://grammalecte/tests.js");
    let oTest = new tests.TestGrammarChecking(gce);
    let sAllRes = "";
    for (let sRes of oTest.testParse()) {
        console.log(sRes+"\n");
        sAllRes += sRes+"\n";
    }
    gce.setOptions(dMemoOptions);
    return sAllRes;
}