/// <summary>
        ///     Checks to ensure we haven't extracted too many bytes, or taken too long. This exists primarily
        ///     to mitigate the risks of quines (archives that contain themselves) and zip bombs (specially
        ///     constructed to expand to huge sizes).
        ///     Ref: https://alf.nu/ZipQuine
        /// </summary>
        /// <param name="additionalBytes"> </param>
        internal void CheckResourceGovernor(long additionalBytes = 0)
        {
            Logger.ConditionalTrace("CheckResourceGovernor(duration={0}, bytes={1})", GovernorStopwatch.Elapsed.TotalMilliseconds, CurrentOperationProcessedBytesLeft);

            if (options.EnableTiming && GovernorStopwatch.Elapsed > options.Timeout)
            {
                throw new TimeoutException(string.Format($"Processing timeout exceeded: {GovernorStopwatch.Elapsed.TotalMilliseconds} ms."));
            }

            if (CurrentOperationProcessedBytesLeft - additionalBytes < 0)
            {
                throw new OverflowException("Too many bytes extracted, exceeding limit.");
            }
        }
Пример #2
0
        /// <summary>
        /// Applique le formatage <paramref name="cf"/> aux caractères dans le <see cref="Range"/>
        /// <paramref name="toR"/> en utilisant la <see cref="Config"/> <paramref name="inConf"/>.
        /// </summary>
        /// <param name="cf">Le <see cref="CharFormatting"/> à appliquer. Attention: ne devrait pas
        /// l'être, mais il y a eu des cas où <paramref name="cf"/> était <c>null</c>.</param>
        /// <param name="toR">Le <see cref="Range"/> à formater.</param>
        /// <param name="inConf">La <see cref="Config"/> à utiliser le cas échéant.</param>
        private void ApplyCFToRange(CharFormatting cf, Range toR, Config inConf)
        {
            logger.ConditionalTrace("ApplyCFToRange");
            // 24.01.2021: J'ai reçu une copie d'écran d'une erreur qui provenait visiblement de
            // l'incapacité de Word à appliquer une couleur. J'ai donc décidé d'intercepter de
            // telles erreurs directement ici.
            // 31.01.2021: Entre temps, j'ai une explication possible et j'ai changé la façon de
            // mettre en couleur. Je laisse quand même les try / catch.
            if (cf != null)
            {
                // **************************** GRAS ********************************
                try
                {
                    if (cf.bold)
                    {
                        toR.Bold = (int)Microsoft.Office.Core.MsoTriState.msoTrue;
                    }
                    else if (cf.ForceNonBold(inConf))
                    {
                        toR.Bold = (int)Microsoft.Office.Core.MsoTriState.msoFalse;
                    }
                }
                catch (Exception e)
                {
                    ErrorMsgACTR(cf, toR, "gras", e);
                }

                // **************************** ITALIQUE ********************************
                try
                {
                    if (cf.italic)
                    {
                        toR.Italic = (int)Microsoft.Office.Core.MsoTriState.msoTrue;
                    }
                    else if (cf.ForceNonItalic(inConf))
                    {
                        toR.Italic = (int)Microsoft.Office.Core.MsoTriState.msoFalse;
                    }
                }
                catch (Exception e)
                {
                    ErrorMsgACTR(cf, toR, "italique", e);
                }

                // **************************** SOULIGNÉ ********************************
                try
                {
                    if (cf.underline)
                    {
                        toR.Underline = WdUnderline.wdUnderlineSingle;
                    }
                    else if (cf.ForceNonUnderline(inConf))
                    {
                        toR.Underline = WdUnderline.wdUnderlineNone;
                    }
                }
                catch (Exception e)
                {
                    ErrorMsgACTR(cf, toR, "souligné", e);
                }

                // if (cte.cf.caps) // capitalize
                // TBD

                // **************************** COULEUR ********************************
                try
                {
                    if (cf.changeColor) // set new
                    {
                        toR.Font.Color = (WdColor)(int)cf.color;
                        // On peut aussi coloriser en utilisant Font.Fill:
                        // toR.Font.Fill.ForeColor.RGB = cf.color;
                        // L'avantage c'est qu'il s'agit d'un remplissage des caractères et qu'on peut
                        // par exemple faire des fondus. L'inconvénient c'est que ça plante avec les anciens
                        // fichiers .doc et que c'est plus lent.
                        // J'ai d'abord fait une distinction entre les deux modes, en interceptant
                        // l'exception, mais ça ne vaut pas la peine tant qu'on n'offre pas plus de
                        // possibilités de formater.
                    }
                    else if (cf.ForceBlackColor(inConf))
                    {
                        toR.Font.Color = (WdColor)(int)ColConfWin.predefinedColors[(int)PredefCol.black];
                    }
                }
                catch (Exception e)
                {
                    ErrorMsgACTR(cf, toR, "mise en couleur", e);
                }

                // **************************** SURLIGNAGE ********************************
                try
                {
                    if (cf.changeHilight)
                    {
                        WdColorIndex wdCi;
                        if (mapRGBtoColI.TryGetValue(cf.hilightColor, out wdCi))
                        {
                            toR.HighlightColorIndex = wdCi;
                        }
                    }
                    else if (cf.ForceHilightClear(inConf))
                    {
                        // il y a un bug sur les espaces, on met donc d'abord du blanc partout
                        // avant d'effacer.
                        toR.HighlightColorIndex = WdColorIndex.wdWhite;
                        toR.HighlightColorIndex = WdColorIndex.wdNoHighlight;
                    }
                }
                catch (Exception e)
                {
                    ErrorMsgACTR(cf, toR, "surlignage", e);
                }

                // **************************** ARC ********************************
                try
                {
                    if (cf.drawArc)
                    {
                        // Let's get rid of any special char before and after the effective text.
                        // We could possibly do that for each case, but arcs seems to be the only
                        // one requesting it, in the other cases, setting a color to an undisplayed
                        // character does not really matter.

                        Range           ran     = toR.Duplicate;
                        MatchCollection matches = TheText.rxWords.Matches(ran.Text);
                        if (matches.Count > 0)
                        {
                            // beg and end are zero based in ran.Text
                            // beg is the first character in a word, end - 1 is the last character
                            // in a word.
                            string texte = ran.Text;
                            int    beg   = matches[0].Index;
                            Match  m     = matches[matches.Count - 1];
                            int    end   = m.Index + m.Length; //char after the match so that end-beg == length

                            // Il peut semble-t-il arriver que des caractères spéciaux se trouvent au début de Text et
                            // qu'ils soient comptés différemment pour Start que pour Text... Probablement qqch à voir
                            // avec UTF-8 vs. UTF-16 ou un truc du genre...

                            // On corrige donc beg pour qu'il corresponde bien au premier caractère voulu. end doit
                            // aussi être corrigé, le cas échéant.

                            string wishedChar = texte.Substring(beg, 1);
                            int    i          = 0;
                            foreach (Range c in ran.Characters)
                            {
                                if (c.Text == wishedChar)
                                {
                                    break;
                                }
                                i++;
                            }
                            Debug.Assert(i < ran.Characters.Count);
                            int delta = beg - i;
                            beg = i;
                            end = end - delta;

                            ran.SetRange(ran.Start + beg, ran.Start + end);

                            int pageNr = ran.Information[WdInformation.wdActiveEndPageNumber];
                            logger.ConditionalTrace("Page Number {0}", pageNr);
                            if (lastPage == 0)
                            {
                                lastPage = pageNr;
                            }
                            else if (pageNr > lastPage)
                            {
                                lastPage = pageNr;
                                ran.Select();
                            }

                            _ = ran.Information[WdInformation.wdHorizontalPositionRelativeToPage];
                            // Ne me demandez pas pourquoi il faut le faire deux fois... Mais seul le
                            // 2e appel donne le bon résultat... PAE 06.02.2021

                            float x0         = ran.Information[WdInformation.wdHorizontalPositionRelativeToPage];
                            float y0         = ran.Information[WdInformation.wdVerticalPositionRelativeToPage];
                            float fontHeight = ran.Font.Size;
                            y0 += fontHeight;
                            y0 += inConf.arcConf.Decalage;
                            float lineheight = ran.ParagraphFormat.LineSpacing;
                            float h          = (inConf.arcConf.Hauteur / 100.0f) *
                                               (float)Math.Sqrt(20.0f * (Math.Max(1, lineheight - fontHeight)));


                            Range endPosition = ran.Duplicate;
                            endPosition.Collapse(WdCollapseDirection.wdCollapseEnd);
                            float x1 = endPosition.Information[WdInformation.wdHorizontalPositionRelativeToPage];
                            float w  = x1 - x0; // width

                            float[,] thePoints0 = new float[4, 2]
                            {
                                { x0, y0 },
                                { x0 + (((float)(100 - inConf.arcConf.Ecartement) / 200.0f) * w), y0 + h },
                                { x0 + (((float)(100 + inConf.arcConf.Ecartement) / 200.0f) * w), y0 + h },
                                { x1, y0 },
                            };

                            Shape s =
                                ColorizationMSW.thisAddIn.Application.ActiveDocument.Shapes.AddCurve(
                                    thePoints0);
                            s.Line.ForeColor.RGB = cf.arcColor;
                            s.Line.Weight        = inConf.arcConf.Epaisseur;
                            s.Name = "arc";

                            if (s.Anchor.Start <= ran.End)
                            {
                                nrArcs++;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    ErrorMsgACTR(cf, toR, "arcs", e);
                }

                // **************************** EEFACER ARCS ********************************
                try
                {
                    if (cf.removeArcs)
                    {
                        List <Shape> toRemoveShapes = new List <Shape>(toR.ShapeRange.Count);
                        foreach (Shape s in toR.ShapeRange)
                        {
                            if (s.Name == "arc")
                            {
                                toRemoveShapes.Add(s);
                            }
                        }
                        int i = 0;
                        foreach (Shape s in toRemoveShapes)
                        {
                            if (i % 30 == 0)
                            {
                                ProgressNotifier.thePN.InProgress((int)(((float)i / (float)toRemoveShapes.Count) * 100.0f));
                            }
                            i++;
                            s.Delete();
                        }
                    }
                }
                catch (Exception e)
                {
                    ErrorMsgACTR(cf, toR, "effecer arcs", e);
                }
            }
            else
            {
                logger.Error("ApplyCFToRange with cf == null");
                Debug.Assert(false);
            }
        }
Пример #3
0
        /// <summary>
        /// Calcule les syllabes avec la <see cref="Config"/> donnée. La liste 'syls' est remplie.
        /// </summary>
        /// <param name="forceDierese">Indique s'il faut forcer la diérèse. Si <c>true</c> les
        /// 'i' suivis de voyelle comme dans 'hier' sont considérés comme une syllabe à part:
        /// 'hi-er'. Si <c>false</c> 'hier' correspond à une seule syllabe.</param>
        public void ComputeSyls(bool forceDierese = false)
        {
            logger.ConditionalTrace(ConfigBase.cultF, "ComputeAndColorSyls {0}", GetWord());
            SylInW    siw;
            int       i, j;
            SylConfig sylConfig = theConf.sylConf;

            // Algorithme de Marie-Pierre
            syls = new List <SylInW>((Last - First) / 2);

            // créons une syllabe pour chaque phonème
            for (i = 0; i < phons.Count; i++)
            {
                syls.Add(new SylInW(phons[i]));
            }

            logger.ConditionalTrace("Etape 1 {0} --> {1}, {2}", GetWord(), Syllabes(), GetPhonSyllabes());

            if (syls.Count > 1)
            {
                // Si le décodage est standard dupliquer les phonèmes qui comportent des consonnes doubles
                if (sylConfig.DoubleConsStd)
                {
                    for (i = 0; i < syls.Count; i++)
                    {
                        if (syls[i].EstConsonneRedoublee())
                        {
                            siw = new SylInW(syls[i]);
                            syls[i].ReduitADerniereLettre();
                            siw.ReduitAPremiereLettre();
                            syls.Insert(i, siw);
                        }
                    }
                }
                logger.ConditionalTrace("Etape 2 {0} --> {1}, {2}", GetWord(), Syllabes(), GetPhonSyllabes());

                // Il y a une série de cas spéciaux où deux sons ne forment qu'une syllabe
                // par exemple [bkptgdfv][lR] ou [y][i] ou [u]([i]|[e_tilda]|[o_tilda])
                // (la notation est un peu libre :-)
                for (i = 0; i < syls.Count - 1; i++)
                {
                    if (FusionnerSyllabes(syls, i, i + 1, forceDierese))
                    {
                        // mixer les deux phonèmes puis raccourcir la chaîne
                        syls[i].AbsorbeSuivant(syls[i + 1]);
                        syls.RemoveAt(i + 1);
                        logger.ConditionalTrace("Etape 3-{0} {1} --> {2}, {3}", i, GetWord(), Syllabes(), GetPhonSyllabes());
                        i--; // faire en sorte que la prochaine itération considère le nouveau
                             // phonème fusionné et son successeur
                    }
                }

                // construire les syllabes par association de phonèmes consonnes et voyelles
                // Les syllabes sont constituées de tout ce qui précède un phonème voyelle
                // jusqu'à la syllabe précédente ou le début du mot.
                // De plus si le phonème voyelle est suivi de deux consonnes, la première fait
                // partie de la première syllabe.

                i = 0;
                j = 0; // début de la syllabe
                while (i < syls.Count)
                {
                    logger.ConditionalTrace("Etape fusion consonnes et voyelles i:{0}, j:{1} {2} --> {3}, {4}"
                                            , i, j, GetWord(), Syllabes(), GetPhonSyllabes());
                    if (syls[i].EstVoyelle(forceDierese))
                    {
                        // fusionner les syllabes de j à i
                        for (int k = 0; k < (i - j); k++)
                        {
                            syls[j].AbsorbeSuivant(syls[j + 1]);
                            syls.RemoveAt(j + 1);
                        }
                        i = j;
                        j++;
                        logger.ConditionalTrace("Etape 4A i:{0}, j:{1} {2} --> {3}, {4}",
                                                i, j, GetWord(), Syllabes(), GetPhonSyllabes());

                        // si les deux lettres qui suivent sont des consonnes, la première fait partie de la syllabe que nous venons de créer
                        // A condition qu'elles ne soient pas toutes les deux dans la même syllabe.
                        if (j < syls.Count)
                        {
                            int pos = syls[j].First; // position de la lettre suivante dans le texte sous-jacent
                            if (syls[j].Last == syls[j].First &&
                                pos < this.Last &&
                                EstConsonne(GetChar(pos)) &&
                                EstConsonne(GetChar(pos + 1)))
                            {
                                syls[j - 1].EtendDroite(1);
                                if (!syls[j].ReduitGauche(1))
                                {
                                    syls.RemoveAt(j);
                                }
                            }
                        }
                        logger.ConditionalTrace("Etape 4B i:{0}, j:{1} {2} --> {3}, {4}",
                                                i, j, GetWord(), Syllabes(), GetPhonSyllabes());
                    }
                    i++;
                } // while

                logger.ConditionalTrace("Etape 5 i:{0}, j:{1} {2} --> {3}, {4}",
                                        i, j, GetWord(), Syllabes(), GetPhonSyllabes());

                // précaution de base : si pas de syllabes reconnues, on concatène simplement les phonèmes
                if (j == 0)
                {
                    // le mot ne comprend pas de voyelles --> une seule syllabe
                    syls.Clear();
                    siw = new SylInW(this, this.First, this.Last, Phonemes.firstPhon);
                    syls.Add(siw);
                    logger.ConditionalTrace("Etape 6A i:{0}, j:{1} {2} --> {3}, {4}",
                                            i, j, GetWord(), Syllabes(), GetPhonSyllabes());
                }
                else
                {
                    // il ne doit rester à la fin que les lettres muettes ou des consonnes qu'on ajoute à la dernière syllabe
                    while (j < syls.Count)
                    {
                        syls[j - 1].AbsorbeSuivant(syls[j]);
                        syls.RemoveAt(j);
                        j++;
                    }
                    logger.ConditionalTrace("Etape 6B i:{0}, j:{1} {2} --> {3}, {4}",
                                            i, j, GetWord(), Syllabes(), GetPhonSyllabes());
                }
                // ###############################################################################
                // # Traitement spécial de de la dernière syllabe dans les modes oral et poésie. #
                // ###############################################################################

                if ((syls.Count > 1) && (syls[syls.Count - 1].P == Phonemes.q_caduc))
                {
                    // s'il y a plus d'une syllabe, il y a aussi plus d'un phonème
                    if (sylConfig.mode == SylConfig.Mode.oral)
                    {
                        // si nous sommes en mode oral, les e caducs des dernières syllabes
                        // doivent être concaténés avec la syllabe précédente
                        syls[syls.Count - 2].AbsorbeSuivant(syls[syls.Count - 1]);
                        syls.RemoveAt(syls.Count - 1);
                        logger.ConditionalTrace("Etape 7A {0} --> {1}, {2}",
                                                GetWord(), Syllabes(), GetPhonSyllabes());
                    }
                    else if (sylConfig.mode == SylConfig.Mode.poesie)
                    {
                        logger.ConditionalTrace("Mode poésie. Syllabes avant le traitement: {0}",
                                                Syllabes());
                        // voir http://mamiehiou.over-blog.com/article-versification-comment-compter-les-pieds-syllabes-d-un-vers-97149081.html
                        // dont nous nous inspirons ici. Il faut toutefois noter que quand le
                        // "e" ne compte pas pour un pied, nous le relions simplement avec la
                        // syllabe précédente, ce qui n'est pas tout à fait correct au niveau
                        // de la prononciation.

                        // En gros on peut dire que si le mot suivant commence par une voyelle
                        // (ou équivalent), le e-caduc ne se prononce pas, sauf s'il y a une laison.
                        // Si le mot suivant commence par une consonne (ou équivalent) le e-caduc
                        // se prononce.

                        string txt = T.ToLowerString();
                        string wrd = ToLowerString();
                        ComportementMotSuivant cms = ComportementMotSuivant.undef;

                        int startNextWord = Last + 1;
                        // cherchons le début du prochain mot (ou la fin de ligne...)
                        while (startNextWord < txt.Length &&
                               (txt[startNextWord] == ' ' ||
                                txt[startNextWord] == '\t' ||
                                txt[startNextWord] == ',' || // la virgule n'empêche pas l'influence du mot suivant.
                                txt[startNextWord] == '!' || // ça pourrait dépendre des situations...
                                txt[startNextWord] == '?' || // ça pourrait dépendre des situations...
                                txt[startNextWord] == '.' || // ça pourrait dépendre des situations...
                                txt[startNextWord] == '"' ||
                                txt[startNextWord] == '«' ||
                                txt[startNextWord] == '»' ||
                                txt[startNextWord] == '“' ||
                                txt[startNextWord] == '”' ||
                                txt[startNextWord] == '‘' ||
                                txt[startNextWord] == '’' ||
                                txt[startNextWord] == '-' ||
                                txt[startNextWord] == '—' ||
                                txt[startNextWord] == ';' ||
                                txt[startNextWord] == ':' // ça pourrait dépendre des situations...
                               ))
                        {
                            startNextWord++;
                        }

                        // cherchons la fin du mot suivant
                        int endNextWord = startNextWord;
                        while (endNextWord < txt.Length &&
                               (EstConsonne(txt[endNextWord]) || EstVoyelle(txt[endNextWord])))
                        {
                            endNextWord++;
                        }
                        // startNextWord est l'index du début du mot suivant. S'il y a des
                        // lettres, endNextWord est celui de la lettre qui suit le mot.
                        // S'il n'y a pas de lettres, endNextWord == startNextWord
                        string nextWord = null;
                        if (endNextWord > startNextWord)
                        {
                            nextWord = txt.Substring(startNextWord, endNextWord - startNextWord);
                            logger.ConditionalTrace("nextWord: {0}", nextWord);
                        }

                        if (startNextWord < txt.Length)
                        {
                            // il peut y avoir un mot suivant.
                            if (Disjonction(nextWord))
                            {
                                cms = ComportementMotSuivant.consonne;
                            }
                            else if (Liaison(nextWord))
                            {
                                cms = ComportementMotSuivant.voyelle;
                            }
                            else if (txt[startNextWord] == 'y')
                            {
                                // Le cas normal est que le y se comporte comme une consonne
                                // et le e-caduc forme une syllabe). Les exceptions sont
                                // interceptées par "Liaison"
                                cms = ComportementMotSuivant.consonne;
                            }
                            else if (TextEl.EstVoyelle(txt[startNextWord]))
                            {
                                cms = ComportementMotSuivant.voyelle;
                            }
                            else if (txt[startNextWord] == 'h')
                            {
                                // Le 'h' mérite un dictionnaire à lui tout seul
                                if (HAspire(nextWord))
                                {
                                    cms = ComportementMotSuivant.consonne;
                                }
                                else
                                {
                                    // h muet
                                    cms = ComportementMotSuivant.voyelle;
                                }
                            }
                            else if (TextEl.EstConsonne(txt[startNextWord]))
                            {
                                cms = ComportementMotSuivant.consonne;
                            }
                            else
                            {
                                // Il ne s'agit pas d'un lettre. Donc soit de la ponctuation,
                                // une fin de ligne ou autre chose... On traite ce cas comme
                                // une fin de vers.
                                cms = ComportementMotSuivant.fin;
                            }
                        }
                        else
                        {
                            // C'est la fin du texte.
                            cms = ComportementMotSuivant.fin;
                        }
                        logger.ConditionalTrace("cms: {0}", cms.ToString());
                        switch (cms)
                        {
                        case ComportementMotSuivant.consonne:
                            // la syllabe est prononcée, on la laisse.
                            break;

                        case ComportementMotSuivant.voyelle:
                            if (wrd[wrd.Length - 1] == 's' || wrd[wrd.Length - 1] == 't')
                            {
                                // il y a une liaison, la syllabe se prononce.
                                // L'existence d'un eliaison est probablement plus compliquée
                                // à identifier (il y certainement une foule d'exceptions)
                                // :-) Commençons quand même comme ça...
                            }
                            else
                            {
                                // la syllabe ne se prononce pas.
                                syls[syls.Count - 2].AbsorbeSuivant(syls[syls.Count - 1]);
                                syls.RemoveAt(syls.Count - 1);
                            }
                            break;

                        case ComportementMotSuivant.fin:
                            // la syllabe ne se prononce pas.
                            syls[syls.Count - 2].AbsorbeSuivant(syls[syls.Count - 1]);
                            syls.RemoveAt(syls.Count - 1);
                            break;

                        default:
                            logger.Error("ComportementMotSuivant {0} non traité", cms);
                            break;
                        }
                        logger.ConditionalTrace("Etape 7A {0} --> {1}, {2}",
                                                GetWord(), Syllabes(), GetPhonSyllabes());
                    }
                }
            } // if (syls.Count > 1)

            logger.ConditionalTrace("Résultat {0} --> {1}, {2}",
                                    GetWord(), Syllabes(), GetPhonSyllabes());
        }