objets/CLatex.js

/*
 * MathGraph32 Javascript : Software for animating online dynamic mathematics figures
 * https://www.mathgraph32.org/
 * @Author Yves Biton (yves.biton@sesamath.net)
 * @License: GNU AGPLv3 https://www.gnu.org/licenses/agpl-3.0.html
 */
import { addTypeset } from 'src/kernel/addLatex'
import { cens } from 'src/kernel/dom'
import NatObj from '../types/NatObj'
import NatCal from '../types/NatCal'
import Complexe from '../types/Complexe'
import Pointeur from '../types/Pointeur'
import StyleEncadrement from '../types/StyleEncadrement'
import { alignLeft, chaineNombre, codeLatexFracCont, decompPrim, fracCont, MAX_VALUE, pgcd, zero, zero13 } from '../kernel/kernel'
import CAffLiePt from './CAffLiePt'
import CCommentaire from './CCommentaire'
import CListeObjets from './CListeObjets'
import Nat from '../types/Nat'
import $ from 'jquery'

export default CLatex

/**
 * Classe représentant un affichage LaTeX sur la figure.
 * @constructor
 * @extends CCommentaire
 * @param {CListeObjets} listeProprietaire  La liste propriétaire.
 * @param {CImplementationProto} impProto  null ou la cosntruction ppropriétaire.
 * @param {boolean} estElementFinal  true si l'objet est un élément final de construction.
 * @param {Color} couleur  La coileur d'écriture
 * @param {number} xNom  L'abscisse d'affichage.
 * @param {number} yNom  L'ordonnée d'affichage.
 * @param {number} decX  Décalage horizontal d'affichage.
 * @param {number} decY  Décalage vertical d'affichage.
 * @param {boolean} masque  true si l'objet est masqué.
 * @param {CPt} pointLie  null si l'affichage est libre ou pointe sur le point auquel il est lié.
 * @param {number} taillePolice  Donne la taille de la police utilisée.
 * @param {number} encadrement entier pour le style d'encadrement (0, 1 ou 2, voir CAffLiePt).
 * @param {boolean} effacementFond  true si le fond doit être effacé avant écritrue.
 * @param {Color} couleurFond  La couleur de fond.
 * @param {number} alignementHorizontal  0 pour alignement gauche, 1 pour centre, 2 pour droite.
 * @param {number} alignementVertical  0 pour alignement vers le haut, 1 pour centré, 2 pour bas.
 * @param {string} chaineCommentaire  Contient le code LaTeX.
 * @param {CValeurAngle} angText  L'angle du texte par rapport à l'horizontale
 * @param {boolean} fixed true si l'affichage est punaisé et ne peut pas être capturé à la souris
 * @returns {CLatex}
 */
function CLatex (listeProprietaire, impProto, estElementFinal, couleur, xNom, yNom,
  decX, decY, masque, pointLie, taillePolice, encadrement, effacementFond, couleurFond, alignementHorizontal,
  alignementVertical, chaineCommentaire, angText, fixed) {
  if (arguments.length === 1) CCommentaire.call(this, listeProprietaire)
  else {
    CCommentaire.call(this, listeProprietaire, impProto, estElementFinal, couleur, xNom, yNom,
      decX, decY, masque, pointLie, taillePolice, encadrement, effacementFond, couleurFond, alignementHorizontal,
      alignementVertical, chaineCommentaire, alignLeft, angText, fixed)
    this.chaineCommentaire = chaineCommentaire
  }
  // Spécial JavaScript : chaineAffichee = contiendra la chaîne utilisée lors de l'affichage précédent.
  // Si c'est la même, update ne fera pas appel à createg mais on changera simplement des coordonnées d'affichage du composant.
  this.chaineAffichee = ''
  // this.div = null // Supprimé version 6.4.8
}
CLatex.prototype = new CCommentaire()
CLatex.prototype.constructor = CLatex
CLatex.prototype.superClass = 'CCommentaire'
CLatex.prototype.className = 'CLatex'

function codeErreur (code) {
  return '\\textcolor{red}{\\text{' + code + ' error}}'
}

// Modification version 8.7.3 : on passe un troisième paramètre impProto seulement dans le cas
// où on appelle getClone depuis CImplementationProto.prototype.implemente sur un objet qui
// a été obtenu par proto.getClone où proto est un CPrototype
CLatex.prototype.getClone = function (listeSource, listeCible, impProto = null) {
  const ind1 = listeSource.indexOf(this.pointLie)
  const ind2 = listeSource.indexOf(this.impProto)
  const angTextClone = this.angText.getClone(listeSource, listeCible)
  const ptelb = new CLatex(listeCible, listeCible.get(ind2, 'CImplementationProto'),
    this.estElementFinal, this.couleur, this.xNom, this.yNom, this.decX, this.decY, this.masque,
    listeCible.get(ind1, 'CPt'), this.taillePolice, this.encadrement,
    this.effacementFond, this.couleurFond, this.alignementHorizontal,
    this.alignementVertical, this.chaineCommentaire, angTextClone, this.fixed)
  if (impProto) ptelb.impProto = impProto
  ptelb.listValDynUsed = new CListeObjets(listeCible.uniteAngle, listeCible.pointeurLongueurUnite)
  if (listeCible.className !== 'CPrototype') ptelb.determineDependances()
  // Ligne suivante nécessaire car utilisé pour les exportations tikz
  ptelb.id = this.id
  return ptelb
}

CLatex.prototype.getNature = function () {
  return NatObj.NLatex
}

CLatex.prototype.setClone = function (ptel) {
  CAffLiePt.prototype.setClone.call(this, ptel)
  this.chaineLatex = ptel.chaineLatex
}

CLatex.prototype.rendChaineAffichage = function () {
  return this.chaineLatex
}

/**
 * Fonction déterminant quels sont les calculs ou fonctions dont le commentaire dépend de façon dynamique.
 * @param indiceReel Si présent c'est qu'on est en train d'utiliser un commentaire
 * dans une boîte de dialogue d'aperçu et c'est alors l'indice du vrai commentaire qu'on est en train d'éditer
 */
CLatex.prototype.determineDependances = function (indiceReel = -1) {
  let indicecommentaire, jdeb, j, indparf, ch, st, nomvaleur, pValeur, nomvaleur2, pValeur2
  const chaineAAnalyser = this.chaineCommentaire.replace(/ /g, '')

  this.listValDynUsed.retireTout()
  // Quand on recherche si c'est bien le nom d'une valeur valide
  // Il ne faut pas que la valeur ait été définie après l'affichage de valeur
  let estDansListe = true
  if (indiceReel !== -1) indicecommentaire = indiceReel
  else indicecommentaire = this.listeProprietaire.indexOf(this)
  if (indicecommentaire === -1) {
    indicecommentaire = this.listeProprietaire.longueur() - 1
    estDansListe = false // Le LaTex est en train d'être lu et n'est pas encore dans la liste
  }
  // On examine la chaine à la recherche de #Val(
  const len = chaineAAnalyser.length
  // Ajout version 6.7 : Traitement des codes \ValFrac qui renvoie le code LaTeX de la fraction continue de l'argument à 10^(-12) près
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\ValFrac{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 9)
    if (indparf === -1) break
    else {
      // On crée une chaine formé de ce qu'il y a entre \Val( et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 9, indparf).trim()
      // On retire les éventuels espaces de cete chaine
      // On sépare cette chaine avec les virgules
      st = ch.split(/\s*,\s*/)
      if (st.length === 0) j = indparf + 1
      else {
        nomvaleur = st[0]
        // On recherche si c'est bien le nom d'une valeur valide
        // Il ne faut pas que la valeur ait été définie après l'affichage de valeur
        // Très important : quand determineDependances est appelé
        // par getClone() de CCommentaire, le commentaire n'a pas encoré été rajouté
        // à la liste clone et ainsi indiceCommentaire renvoie -1.
        // dans ce cas, indiceCommentaire doit valoir le nombre d'éléments actuels
        // de la liste clone qui le possède
        pValeur = this.pointeur(NatCal.NTteValPourComDynSaufFoncSaufComp, nomvaleur, indicecommentaire)
        if (pValeur === null) j = indparf + 1
        else {
          this.listValDynUsed.add(pValeur)
          j = indparf + 1
        }
      }
    }
  }

  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\Val{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 5)
    if (indparf === -1) break
    else {
      // On crée une chaine formé de ce qu'il y a entre \Val( et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 5, indparf).trim()
      // On retire les éventuels espaces de cete chaine
      // On sépare cette chaine avec les virgules
      st = ch.split(/\s*,\s*/)
      if (st.length === 0) j = indparf + 1
      else {
        nomvaleur = st[0]
        // On recherche si c'est bien le nom d'une valeur valide
        // Il ne faut pas que la valeur ait été définie après l'affichage de valeur
        // Très important : quand determineDependances est appelé
        // par getClone() de CCommentaire, le commentaire n'a pas encoré été rajouté
        // à la liste clone et ainsi indiceCommentaire renvoie -1.
        // dans ce cas, indiceCommentaire doit valoir le nombre d'éléments actuels
        // de la liste clone qui le possède
        // Modifié version 4.7.2
        // CValDyn pValeur = pointeurValeurOuFonction(nomvaleur,indicecommentaire);
        pValeur = this.pointeur(NatCal.NTteValPourComDynSaufFonc, nomvaleur, indicecommentaire)
        if (pValeur === null) j = indparf + 1
        else {
          this.listValDynUsed.add(pValeur)
          j = indparf + 1
        }
      }
    }
  }
  // Version 7.3 : On rajoute un code LaTeX \Decomp qui donne le décomposition en produit de facteurs
  // premiers d'un entier supérieur ou égal à 2 et\DecompFull qui fait la même chose sans exposant
  // en répétant les facteurs premiers
  const tab = ['\\DecompFull{', '\\Decomp{']
  for (let k = 0; k < 2; k++) {
    j = 0
    while (((jdeb = chaineAAnalyser.indexOf(tab[k], j)) !== -1) && j < len) {
      // On recherche la parenthèse fermante correspondante
      const decal = tab[k].length // La longueur de la chaîne recherchée
      indparf = chaineAAnalyser.indexOf('}', jdeb + decal)
      if (indparf === -1) break
      else {
        // On crée une chaine formé de ce qu'il y a entre \Decomp( et la parenthèse fermante
        ch = chaineAAnalyser.substring(jdeb + decal, indparf).trim()
        // On retire les éventuels espaces de cete chaine
        // On sépare cette chaine avec les virgules
        st = ch.split(/\s*,\s*/)
        if (st.length === 0) j = indparf + 1
        else {
          nomvaleur = st[0]
          // On recherche si c'est bien le nom d'une valeur valide
          // Il ne faut pas que la valeur ait été définie après l'affichage de valeur
          // Très important : quand determineDependances est appelé
          // par getClone() de CCommentaire, le commentaire n'a pas encoré été rajouté
          // à la liste clone et ainsi indiceCommentaire renvoie -1.
          // dans ce cas, indiceCommentaire doit valoir le nombre d'éléments actuels
          // de la liste clone qui le possède
          pValeur = this.pointeur(NatCal.NTteValRPourComDyn, nomvaleur, indicecommentaire)
          if (pValeur === null) j = indparf + 1
          else {
            this.listValDynUsed.add(pValeur)
            j = indparf + 1
          }
        }
      }
    }
  }
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\For{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 5)
    if (indparf === -1) break
    else {
      // On crée une chaine formé de ce qu'il y a entre \Val( et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 5, indparf).trim()
      // On sépare cette chaine avec les virgules
      st = ch.split(/\s*,\s*/)
      if (st.length === 0) j = indparf + 1
      else {
        nomvaleur = st[0]
        pValeur = this.pointeur(NatCal.NTteValPourComDyn, nomvaleur, indicecommentaire)
        if (pValeur === null) j = indparf + 1
        else {
          this.listValDynUsed.add(pValeur)
          // Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
          j = indparf + 1
        }
      }
    }
  }
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\Calc{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 6)
    if (indparf === -1) break
    else {
      // On crée une chaine formé de ce qu'il y a entre \Val( et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 6, indparf).trim()
      // On sépare cette chaine avec les virgules
      st = ch.split(/\s*,\s*/)
      if (st.length === 0) j = indparf + 1
      else {
        nomvaleur = st[0]
        pValeur = this.pointeur(NatCal.NTteValPourComDyn, nomvaleur, indicecommentaire)
        if (pValeur === null) j = indparf + 1
        else {
          this.listValDynUsed.add(pValeur)
          j = indparf + 1
        }
      }
    }
  }
  // Version 6.7 : Traitement des codes \ForSimpFrac
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\ForSimpFrac{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 13)
    if (indparf === -1) break
    else {
      // On crée une chaine formé de ce qu'il y a entre \Val( et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 13, indparf).trim()
      // On sépare cette chaine avec les virgules
      st = ch.split(/\s*,\s*/)
      if (st.length === 0) j = indparf + 1
      else {
        nomvaleur = st[0]
        pValeur = this.pointeur(NatCal.NTteValPourComDyn, nomvaleur, indicecommentaire)
        if (pValeur === null) j = indparf + 1
        else {
          this.listValDynUsed.add(pValeur)
          // Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
          j = indparf + 1
        }
      }
    }
  }
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\ForSimp{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 9)
    if (indparf === -1) break
    else {
      // On crée une chaine formé de ce qu'il y a entre \Val( et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 9, indparf).trim()
      // On sépare cette chaine avec les virgules
      st = ch.split(/\s*,\s*/)
      if (st.length === 0) j = indparf + 1
      else {
        nomvaleur = st[0]
        pValeur = this.pointeur(NatCal.NTteValPourComDyn, nomvaleur, indicecommentaire)
        if (pValeur === null) j = indparf + 1
        else {
          this.listValDynUsed.add(pValeur)
          // Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
          j = indparf + 1
        }
      }
    }
  }
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\ForRep{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 8)
    if (indparf === -1) break
    else {
      // On crée une chaine formé de ce qu'il y a entre \Val( et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 8, indparf).trim()
      // On sépare cette chaine avec les virgules
      st = ch.split(/\s*,\s*/)
      if (st.length === 0) j = indparf + 1
      else {
        nomvaleur = st[0]
        pValeur = this.pointeur(NatCal.NTteValPourComDyn, nomvaleur, indicecommentaire)
        if (pValeur === null) j = indparf + 1
        else {
          this.listValDynUsed.add(pValeur)
          // Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
          j = indparf + 1
        }
      }
    }
  }
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\CalcSimp{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 10)
    if (indparf === -1) break
    else {
      // On crée une chaine formé de ce qu'il y a entre \Val( et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 10, indparf).trim()
      st = ch.split(/\s*,\s*/)
      if (st.length === 0) j = indparf + 1
      else {
        nomvaleur = st[0]
        pValeur = this.pointeur(NatCal.NTteValPourComDyn, nomvaleur, indicecommentaire)
        if (pValeur === null) j = indparf + 1
        else {
          this.listValDynUsed.add(pValeur)
          // Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
          j = indparf + 1
        }
      }
    }
  }
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\FracRed{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 9)
    if (indparf === -1) break
    else {
      // On crée une chaine formé de ce qu'il y a entre \FracRed{ et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 9, indparf).trim()
      st = ch.split(/\s*,\s*/)
      if (st.length === 0) j = indparf + 1
      else {
        nomvaleur = st[0]
        pValeur = this.pointeur(NatCal.NTteValRPourComDyn, nomvaleur, indicecommentaire)
        if (pValeur === null) j = indparf + 1
        else {
          if (st.length === 1) j = indparf + 1
          else {
            nomvaleur2 = st[1]
            pValeur2 = this.pointeur(NatCal.NTteValRPourComDyn, nomvaleur2, indicecommentaire)
            if (pValeur2 !== null) { // Ligne corrigée version 6.4. Faisait référence à pValeur
              this.listValDynUsed.add(pValeur)
              this.listValDynUsed.add(pValeur2)
            }
            j = indparf + 1
          }
        }
      }
    }
  }
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\If{', j)) !== -1) && j < len) {
    // On recherche la parenthèse fermante correspondante
    indparf = chaineAAnalyser.indexOf('}', jdeb + 4)
    if (indparf === -1) break
    else {
      // On crée une chaine formée de ce qu'il y a entre \if{ et la parenthèse fermante
      ch = chaineAAnalyser.substring(jdeb + 4, indparf).trim()
      pValeur = this.pointeur(NatCal.NTteValPourComDynSaufFonc, ch, indicecommentaire)
      if (pValeur === null) j = indparf + 1
      else {
        this.listValDynUsed.add(pValeur)
        j = indparf + 1
      }
    }
  }
  // Version 8.8 : Si on utilise des insertions de code LaTeX venant d'un autre affichage LaTeX
  // via le code LaTeX spécial \Lat{tagLatex} il faut ajouter à la liste des dépendances celles du LaTeX dont on insère le contenu
  j = 0
  while (((jdeb = chaineAAnalyser.indexOf('\\Lat{', j)) !== -1) && j < len) {
    indparf = chaineAAnalyser.indexOf('}', jdeb + 5)
    if (indparf === -1) break
    else {
      ch = chaineAAnalyser.substring(jdeb + 5, indparf).trim()
      const lat = this.listeProprietaire.getLaTeXByTagBefore(ch, indicecommentaire + (estDansListe ? 0 : 1))
      if (lat !== null) {
        // On a trouvé un code \Lat{ch} valide on rajoute les dépendances de l'affichage LaTeX lat
        // à celles de this
        // On ajoute le latex trouvé à la liste des valeurs utilisées bien que ce ne soit pas une valeur
        // Ainsi si le LaTeX dont le code est inséré dépend d'une valeur dynamique this en dépendra aussi
        this.listValDynUsed.add(lat)
      }
      j = indparf + 1
    }
  }
}

CLatex.prototype.positionne = function (infoRandom, dimf) {
  let ch = this.chaineCommentaire
  if (this.listValDynUsed.longueur() !== 0) {
    ch = this.traiteCodesLatex(ch)
    // Ligne suivante modifiée version 6.8.1 pour un meilleur fonctionnement des macros d'apparition d'objets
    // Si c'est un affichage LaTeX qui était masqué et qu'une macro d'apparition a mis son membre
    // masqué à false, il faut que l'affichage soit créé
    // this.isToBeUpdated = (ch !== this.chaineLatex)
    this.isToBeUpdated = (ch !== this.chaineLatex) || !this.hasgElement
    this.chaineLatex = ch
  } else {
    this.chaineLatex = ch
    // Ligne suivante modifiée version 6.8.1 pour un meilleur fonctionnement des macros d'apparition d'objets
    // Si c'est un affichage LaTeX qui était masqué et qu'une macro d'apparition a mis son membre
    // masqué à false, il faut que l'affichage soit créé
    // this.isToBeUpdated = false
    this.isToBeUpdated = !this.hasgElement
  }
  // CAffLiePt.prototype.positionne.call(this, infoRandom, dimf) // Modifié version 6.4.1
  CAffLiePt.prototype.positionnePourIm.call(this, infoRandom, dimf)
}

/**
 * Attention : Version 6.4.1 : Il faut redéfinir positionneFull pour CLaTeX car sinon c'est le positionneFull
 * de CAffLiePt qyi sera appelé
 * @param {boolean} infoRandom
 * @param {Dimf} dimf
 */
CLatex.prototype.positionneFull = function (infoRandom, dimf) {
  this.positionne(infoRandom, dimf)
  if (this.existe) this.isToBeUpdated = true
}

/**
 * Fonction préparant l'affichage par MathJax en créant un div provisoire
 * @param {boolean} bMemeMasque  Si true la préparation se fait même si l'affichage est caché
 *                               (sert dans la boîte de dialogue de protocole)
 * @returns {void}
 */
CLatex.prototype.setReady4MathJax = function (bMemeMasque) {
  // Modifié version 5.0.4 pour tenir compte des objts dupliqués d'un CLaTeX
  // qui est masqué
  const memeMasque = arguments.length === 0 ? false : bMemeMasque
  if (!this.masque || this.hasDuplicate || memeMasque) {
    this.typeset()
  }
}

CLatex.prototype.createg = function () {
  let w, h, va, decHor, decVer, xdisp, ydisp
  const g = cens('g')

  try { // Modifié version mtgApp
    const s = this.html.firstChild
    const svg = s.cloneNode(true)
    g.appendChild(svg)
    w = parseFloat($(s).attr('width')) * this.ex
    h = parseFloat($(s).attr('height')) * this.ex
    va = parseFloat($(svg).css('vertical-align')) * this.ex
    svg.setAttribute('width', w + 'px')
    svg.setAttribute('height', h + 'px')
    $(svg).css('vertical-align', va + 'px')
    // s.setAttribute("width", w + "px");
    // s.setAttribute("height", h + "px");
    // Lignes suivantes supprimées version 6.4.0
    // var t = Fonte.tailleLatex(this.taillePolice); // Modifié 5.0.2
    // if (h < t) h = t;
    switch (this.alignementHorizontal) {
      case CAffLiePt.alignHorCent :
        decHor = w / 2
        break
      case CAffLiePt.alignHorRight :
        decHor = w
        break
      default : decHor = 0
    }
    xdisp = -decHor
    this.rectAff.x = xdisp - 1
    const decalageBas = 3 + h * 0.03
    switch (this.alignementVertical) {
      case CAffLiePt.alignVerCent :
        decVer = h / 2
        break
      case CAffLiePt.alignVerLow :
        decVer = h + decalageBas
        break
      default : decVer = -decalageBas
    }
    ydisp = -decVer
    this.rectAff.y = ydisp - decalageBas + 1
    this.rectAff.width = w + 2
    this.rectAff.height = h + 2 * decalageBas

    /*
    var clone = s.cloneNode(true);
    clone.setAttribute("x", (this.rectAff.x).toString()+"px");
    clone.setAttribute("y", (this.rectAff.y).toString()+"px");
    clone.setAttribute("width", w+"px");
    clone.setAttribute("height",h+"px");
    clone.setAttribute("style","");
    */
    svg.setAttribute('x', (xdisp).toString() + 'px')
    svg.setAttribute('y', (ydisp).toString() + 'px')

    g.appendChild(svg)
    if (this.effacementFond || (this.encadrement !== StyleEncadrement.Sans)) { this.creeRectangle(g, this.couleurFond) }
    // this.deleteDiv(); // Plus utilisé version 6.4
    // Ligne suivante modifiée version 6.5.2
    // g.setAttribute('pointer-events', 'none')
    g.setAttribute('pointer-events', this.pointerevents)
    // Ajout version 5.0.1 pour compatibilité avec l'explorer qui ne clipe pas correctement
    // Supprimé version mtgApp car pour des lieux d'objets de LaTeX liés à un point lié le point lié peut être hors-fenêtre
    /*
    if ((this.pointLie !== null) && !this.pointLie.dansFenetre)
      g.setAttribute("visibility", "hidden");
    else g.setAttribute("visibility", "visible");
    */
    g.setAttribute('visibility', 'visible')
    // Ajout version Version 6.0 //////////////////////////////////////////
    this.positionneAngText(g)
    /// //////////////////////////////////////////////////////////////////////

    // Ajout version MtgApp pour pouvoir déplacer un CEditeurEquation
    if (this.owner !== null) this.g = g

    //
    return g
  } catch (e) {
    // this.deleteDiv(); // PLus utilisé version 6.4 avec MathJax3
    return g // Retourne un g vide en cas de problème
  }
}
/**
 * @returns {void}
 */
CLatex.prototype.setReady4MathJaxUpdate = function setReady4MathJaxUpdate () {
  if (this.isToBeUpdated || (this.g && (this.g.childNodes.length === 0))) this.setReady4MathJax()
}

CLatex.prototype.update = function update (svg) {
  const oldg = this.g
  if (this.isToBeUpdated) {
    const g = this.createg()
    svg.replaceChild(g, oldg)
    g.setAttribute('id', this.id)
    this.g = g
    // Très important : pour les affichages Latex utilisant le package colortbl il faut rappeler
    // un typeset sur cet élément une fois inséré dans le dom.
    // fix problème du latex avec \columncolor qui donnait un rectangle noir sur https://app.mathgraph32.org/#autoComplete=false&decimalDot=true&displayMeasures=true&dys=true&language=fr&level=2&useLens=false&zoomOnWheel=false&fig=TWF0aEdyYXBoSmF2YTEuMAAAABcAAmZy####AQD#AQAAAAAAAAAAAnYAAAIIAAABAQAAAAAAAAABAAAAHv####8AAAABAApDQ2FsY0NvbnN0AP####8AAnBpABYzLjE0MTU5MjY1MzU4OTc5MzIzODQ2#####wAAAAEACkNDb25zdGFudGVACSH7VEQtGP####8AAAADAAZDSW1hZ2UA#####wAAAAA#gAAAAQAA#####w1Ab2AAAAAAAEBoYAAAAAAAAAAAAAABAAAAAQAAAAEAAAAAAAAAAAEAAAABsQAAAJ0AACRDiVBORw0KGgoAAAANSUhEUgAAAbEAAACdCAYAAAA6yUZIAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAACPYSURBVHhe7d19WNP1#j#wZ8e4Od6xZSkdS5gZ4KlYLFGxzugHeHsSU7BSA8zNbjTsHJn5TbBzfiHnmExLEU8ex1eFY52UmeIpPQLLrdSjxo4jDcRy4M0RLd2ENBTt8#0DtsPe3I2xDfbZ63Fdu658v97rusLYc+#bz10cx3EghBBCPNAv2AZCCCHEU1CIEUII8VgUYoQQQjwWhRghhBCPRSFGCCHEY1GIEUII8VgUYoQQQjwWhRghhBCPRSFGCI#Mmj0Hvn7+rV5jo8YhW6lkuxPi8SjECPECer0e6ekZWLBwIVsixKNRiBHCQx99uA23bjZYX0sUCgCASpUHo9HIdifEY1GIEeIFsrJWIDYmBmgelRHCFxRihBBCPBaFGCFeID09A6UaDQBAIpGwZUI8FoUYITzE7lK07EyUy2UQiURsd0I8FoUYIV5AIpEgK2sFNuTmsiVCPBqFGCE8xO5O#NfhQ9YdioTwCYUYIYQQj0UhRgghxGNRiBFCCPFYFGKEEEI8FoUYIYQQj3UXx3Ec20gIIYR4AhqJEUII8VgUYoTwTF3DbTy36A9IfOlV1DXcZsuE8AqFGHGIVqeDVqdjm0kPq2u4jYSFGfh08#v4#NMiiEdHIb+ohO1GCG9QiBGH6LQ66LQUYr1JXcNtPD35WRwp3IhDX+pw5fJ#EPv005DPfAZPTZ2FqrMX2bcQ4vEoxIjDzGYz20R6yMna63hy4lRcu1iNL3QHIBaLAQCqddkoP3ECP16qwdjRkVCs3EBTjIRXKMSIQ6TRUhjKDWwz6QEna68jMXEGGi6fR9m#vrQGmEXYwyNw#OghZGdnY+Of0jFaGou9B#9t04cQT0UhRogH01edw7TfTgJMtTh2+AsIBAK2i5UsaRbOnTXi8UfDkDj5#2GaPA3nzA1sN0I8CoUYIR5q25cVeGbKRPg01OHwQW2HAWYhEAjw9##diF2f7MQ3B#djzCgJ0nMK2G6EeAwKMUI80LYvK7BkbgJGRTxud4C1ND42BqcrvsacmTOwLn0RJBMScOBrI9uNkF6PQowQD2MJMOmYUSja8WGXA6yl7D+vwImvj2PAXQ347ZMRmLU0m6YYiUehECMOEQQEoLq6hm0mLrb0g514eUoUpGNG4e#b8tmyQ4KCgqD956fYsnkzPv#bejz15JNYuf0A242QXolCjDhELBbj7NmzbDNxodR1O5D75jy8mJTktABraWbCdFSeNCBOGoW3kybhqRkv4VD1NbYbIb2Kx4dYTU0N0tLoseuE31LX7cDmjJfx#nvvYWNuDlt2GoFAgLy#rMexo0fww6kyxEc9ilf#rKKzZaTX8vgQCwgIQM769aipoamtrspWKrFg4UKEho1kSzCZTJg8eYpN29iocQgNGwmTyWTTTlynruE2pv9+ZXOArYFc9hLbxSXEYjEqT5bjf5ak4cOVSzAm7rf4oORrthshPY#jgXkyGbd4cRrbTDowZmwU5+PrZ32VlZXZ1F9bsIALCQ2zaVu2LJ3z8fXjSkpLOY7jOB9fP5s6ca5rPzVycfOWcj6+ftwm1f+yZbcxmUzcxClTuX4DBFzcvKXcQaOZ7UJIj+FFiFVXV3P33jeYM5lMbIl0whJmmzaprG1lZWWcj68fN3hIoE1frrm#BYWY61gCbMBAAXdAq2XLPeKAVssFDh3GDfu1hNu6u5gtE9IjPH46Ec27q8TicOQX0KHNrkpImAEAMJn#O0WoystDbEwMTCaTzdShXq9HbEyM9c#Dhg2jm+xd4GTtdfz25bdwpHAjvtAdQLRUynbpEdFSKT7aewD3BI2EfOYzyMxcQfdnkh7HixADgEWpqVi3zr4F7wULF8LXzx++fv4YEni#tT1bqYSvnz+ylUqb#nw2XCQCAJhNTR9GarUakggJRMOb21t8SKny8pCVtcL65+DgIOs#E+ew3INo2K2yuci3N6hruI0lmu+x4A#v4nTVKWh1WoyKHE1fZEiP4k2IxcfHAwCKiorYUisbcnNxqbbpsRSSiAgAQHp6BtLTM4AWH+jeQCAUAgDOGJtuazhjNEIul0EoaGq3jMRUqjwkJCS0eCdxNkuA1Z891esCDADmfvwNxgULMH#MUAQFBaGkuBhvL1+OxMSZSEic2StGZUMC74evnz9tPvIivAkxAFi0KBXrcuwbjen#3XSLd0xsDFSqPJwxGrF372dAiyk2byBscduDWq2GXCYDAAiETe1GoxFGoxEms8lmKpE4177KK0hMnAGYanGi#HivC7A3dlehruE2MicOt2lPTk7C6apTEAgC8HBIqN2#f4Q4C69CLDkpCQZDOQyGzh8RotfrAQBCgRClGg0++nAbYmNicOtmAyQSCdudt0TN04nWn0fzyOy#IzEzspVKLFHQWTxXMZvNWL14Lq7VnsOqLYXdukbKFd7YXYV9lVew+flfY6D#3Wy56WyZSoXCwh1Yty4HoyJH2#U7SIgz8CrEBAIBkpOS7Po2qCnVQChsCrANuevZsteRSCQ204XC5pGYWq3GhtzcFj1tXesFU0iezGw2I278BJi+v4TsLWq8vLcWHxsusd16zBu7q3Cy9kcceyMSDwr82bKNaKkU356uwrT4eMSNn4C0NEWvmGIk#MarEEPzlGJBwd86#eWxTCcmJsywjj68lUgkahXkIpGoqX1D+wEWLY2GwVDONhM7WQJMLA5HSfF+zHlqJN6fFoK3952BUtuzh#frGm4jbqMeJ2t#xM6U8DZHYO1ZvjwDXx07CkO5AaMiR9u1Tk2Io3gXYkFBQZg6dSpyctofXanVaphMJkgiIrx+s4JQKMSpyopWQS6RSHCqssI63Uicq2WA5alU1inE58VDsDMlHPsqr2DG1vIeuVF+X+UVRK49hkcC+6PkFUmXAszCsvFjzWolZPL5SEicSbfqEJfgXYiheTS2Nb#9C1JLNRoAgFzetImBEHcyGJpGKJYAYz0S2A87U8LxaGB#xG38NzYducB2cYm6htt46eNv8MbuKqydFoK100LYLl0WHx+P01WnEBwUhFGRo5GZ+d8jGoQ4Ay9DLFoqhUAgQH5+24efS5vXw7x9FEbcz2AwIG78BEyLj28zwCwG+t+NdyYOx+bnf42Pj19C5NqjLlsrq2u4DaW2BpFrj2Gg#9049kYkJoUNYrs5TCAQYPVqJQoLd2B3URGdLSNOxcsQg+XwcxsbPCxbxi3nwwhxF0uArVYqsXq1fQfqxwUHoOQVCRRPB2HTvy4gcu1RKLU1OFl7ne3aZfsqr+CN3VUIXXUYJ2uvY#Pzv8baaSEOTR#aI1oqxVfHjiI5OQmJiTNp4wdxirs4juPYRr64b#AQFBbu6DXX9vDNupwcGAyGDkcUpIlWp0Ni4kysViqRnJzElu12qPoaPjZcwr7KKxjo3wfjggWYHDoIjwT263T34KHqazh56Uccqr6GQ9XXMNC#D14eOxSTQgd1+l5nq6mpweI0BXQ6Xbd#Ji0NCbwfJpMJl2ovtlrnJfzE6xDLzFyB6ppq+pB1Ea1Oh8zMTJQUF7Ml0kJ+fgHk8+dDtWmT0z6s0XzDx95TPzSFU+111N28jYF+d+ORwH6t+tXdvI1HhvTDI4H98Whgvx4JrrYUFRVhcZoCwcFByFOpEBTUvavMKMS8D69DrKamBg+HhOJ01alu#3KQ1ijEOpefX4A0hcJtMwLnzA04Z75p0#agwK9XBFZ7zGYzMjNXIGf9eizPyMDy5U3XvzmCQsz78HZNDM3bfJOSXrT7YmBCnMkSYCXF+90SYADwoMAf44IDbF69OcDQYuPHsaNHoNVpMeLhENr4QezG6xBD8waP#IICWkAmbpWWprAGWG+7B7G3EovFKCkuxqJFqUhMnAmZXE6#t6RTvA8xsVgMsTgcRUV72BLhMctjdSxPJmjL2Khx8PXzh1qtZkvdIpPLsbuoiALMQYtSU3G66hTM5msdXiosk8tbnTu7VHsRt2420FSiF+F9iAFAclIy3snMZJtJN4nDw6HTfcE2ezWZXA6DoRxfHTtKAdYNAoEA6sId1kuF48aPt7lUWKvToahoD1JTX7d5H#E+3hFizTvCaJ7duXrbbes9yWw2WwOspHg##WycxHK2LFoajcjRY5CZuQJnz56FTCbH8uUZ9HMm3hFiaL6KKpNGY8QFLPcgUoC5hkAgwPLlGdanSUdInoBAIMCi1FS2K#FCXhNilmeN0SWkxJnYm+gpwFwnKCgIq5VK1NfXw2g00qXCBPCmEBMIBIiPn0prY8Rp2ruJnriOTD4fyzMy8N23pyEQBGBU5Oh2N34Q7+A1IQYAby9fjqKiPbRt18l688#TskuxrZfladaO6OwmeuJ8lp2IlrUwy9Ok8#ML6GnSXsyrQiwoKAhSqbTDZ42RrpFKfwNDuXc9GNNykW90tJQCzE1qamqwLicHeapNNu2WjR#0NGnv5VUhBjueNUb4ZYlCgVs3G9p8SSQStnunWt5ETwHmPgEBAchTbWr32AI9Tdp7eV2IWa7#ae9ZY4S0R6vTWQPMmRf5ks41rWnHs8022KdJx40fTxs#vIDXhRia18byC2g0RuyXn1+A8RRgHsHyNGlxuJieJu0FvDLE4uOnwmAop4VgYhfrTfQ7tlOAeQjLpcIlxfuxu6iIdjDymFeGmOWgJP2P3X1BQUG8#jLQ8ib6zqazSOfcvelCLBbjq2NH6WA0j3lliKH5KqqCgr#RnHk3BQcF45r5GtvMC3QTvfOlKRSQyeVsMyEO4#VDMTsjk8sRHBTcrYfwebuWZ3f4RCaXo6hoDwWYk7EHxAnpLq8diQFAcnIyTSmSViwX+Z6uOkUB5mQCgQAlxfthMJTTiIw4hdeG2I3LR#FQn+0Ivr8#bbf3QgECYasvMHQTvXtQkBFn8roQa7x+AecPvo7zB1+HvyAMU55+GG8vf4vtRnjuhReex5Ilb2LHjh0A3UTvdk3XRm1CUdEepKUp2DIhdvOqELtalQ#j#uno4zMADz1TinsfeR2Lf#8K7txuoGeNOUgsDodWp2Wbe72NH3yAuXNT8GJSMrZs2Yq48ROaD8tSgLmLWCxGSfF+5BcU0GwIcZhXhNidxnqcP#g6TFVb8cCT63H#6D+jj88AAEBA8HRMeGoEVq#KYt9G7BDgwR#4Gz#4ALNnz8LLr7wCgSAA6sIdFGBuZgmyNIWCgow4hPchdqexHmc#TwYABE#chb6DR7NdsCR1FvYVa2m7vZcxGAz44osvMWLECHzxxZfWqUXiXhRkpDt4HWKWAPMXhOGBJ9dbR1+sh8fMQ9yTI#D28mVsifBUy5vovzl5AlOnTsWLSckUZD2Egow4irch1jLA7h#9Z7Zso4#PAKS#kUjPGvMSbd1EX7hjO0QiEV5MSsbZs2fZtxA3oCAjjuBliHUlwCxGx83HQ8PuwebNdACzq6qrPWcatmWAsfcgVlZ8g6lTp9q0EfcSi8UoLNwB+fz5FGTEPhwP#efI#3A1miS2uVM5WXJu2IOBbDPphI+vH9vUK23dms#5+PpxW7fmsyXiJIWFhdyYsVGcj68fV1ZWZlN7bcGCNtvbYvm7On78OFsixAbvRmL1F0pRf6EUQ5#KZUudmiefj5#v3MInO2ldhG#oJnrXU6vVKNVoIBKJAAAmZmq+tLSpZs#DSJOTk6DatKn57B5#L5gm3cerELvTWI+LR9+y2ULfFX0Hj8b8F57C6tXZbIl4MLqJ3j1MJjM25ObCaDRCKBRCEhFhren1ehiNRsTGxti8pyPJyUlYrVRSkJEO8SrEfjixHn0Hj8aAobFsyW5zXpyDEye+oV8ansjMXEE30buJXC6D0WiEXq+HJCICQqHQWlOrdwIAJBGdj8JaoiAjneFNiDVevwDT6XwMebx7V0g9FPEcJkhDkf3u#2dLxMPk5xdgXU4OBZgbFarVAICYFiMuk8kEVV4eAHRpJGZBQcYfrtj9zZsQu1qVj4DgZ+HTbyhb6rKlaW9gu#ozl#zA+WjYsGG98sMlOTmJbqJ3M02pBgCQmJBgbVPl5UEgECA2Jsa6XtZVFGSeLz+#AIOHBDr9UglehNidxnpcq#4EwpAUtuSQx5+cjqiIIKzOpquo7BEcHATztd75YEy6Rsp9jEYjSjUam7BSqZpGYEaj0WZ05ojk5CTEx09F3PgJTv8gJK4lk8uRplCguHg#goKC2HK38CLErhk#gb8gDP6CMLbkkD4+A#Ca7Dmsz93Ilggh7ShtHoVZwspoNMJkNlnrEokEer3e+mdH5KlUiI+fioTEmTRT4gHMZjNGRY6GwVCOr44dRbRUynbpNn6EWPUnCBBNZ5u7JWH2qwi8bwDyVH9hS4SQNhiNRgDAcJEIarUa2UolligU1ilGoUBgXRvrjjyVCmJxOOLGT6Ag68UMBgMeDgmFWByOEheMwCw8PsTuNNbjprkS#YfGsaVu8ek3FEkz4#D+e6vZEiGkDZYpxAULX8cZoxEbcm3PaqrVO1u1OYqCrHfLzy9A5OgxWL48A3kqlWun9dnTz56m7nwJd+afz7LNTvGTqYILGNiXKy3dz5Y6tWxZOufj68cNHhLIXb16lS3zSmxcHHdAq2WbCXG5eTIZ98SoSM5kMrEl0kPmyWTcvfcNdttngsePxG5cPtqtc2Ed8ReE4fn4KKg+WMuWOmXZatxyezFficPF0GnpoaLE#WhE1nu4Y#2rLR4fYjfNFeh7X+tnhDnLW0sXo3B3SZd2Q6nVauutBU1#bjroyVcunSogpBNN01UBFGQ9yF3rX23x+BC78f0xp5wNa0#wo1Mw4Tdh+PMK+581VtgcWgpFGkQiEfR6fbd3ZfVmPzXewHe1p#CP8q3Wl6ZSjapLBpw3fct2J8TpCpufAyeTz2dLxMXcuv7VBo8PMTRvwnCl3y16DX#fXmTXtzyTyQSNRgOhUAi5TGY99Mnn0VhDYwPOXWnamWZxzvQt#lG+FWuKF2Px9nisKV4MTaUaV67X2vQjxBkEAgFKivejpqYGMrmcLRMXaXn+a1FqKlt2i7s4juPYRk#ReP0CjPunI2T6UbbkdJHihzBP#gpeS32TLdnIViqRnp6BhIQEfPThNuj1eoyNGgeRSIRTlRVsd15Y#NZinL7wDfbk72NLAIAr12tRdcmAqkvH8a8z+#HwYDGeCU9ByBC6SYM4l9lsRtz4CRCLw60PPCXOZ#k5A4C6cIdbpw9ZHj0Sa7x+wWkHnDuT8nwMslYq2eZWLCOuxIQZQPMBT4lEAqPRCHXzZg++GTBgAEzf17HNVoP6BSJq+ESkRC3Fmpm78fiDT2Lr4XeRvms2Dp#5J9udEIdZRmQGQzmNyFzEkfUvtVqN9PQMhIaNtN7iYhEaNhJDAu93fMmF3a7oSa5fOuLQwy87c+vH89y3+o+5Date515+MZZ74rEgLmBgP65fv34dPqSvrKyM8#H140JCw2zaV2Vncz6+ftwLs2bbtPPFtp0F3CORv2abO3Xou33csk9mcSs+nc+du3qaLRPiMJPJxD0xKpKbJ5OxJdINloeVrl23ji21y#L5Z3lNmjTZpj5p0mTOx9ePW7Ys3abdXh4dYj+ZKrhv98SwzV1y+1Ydd#3SEe6jv2ZwL78Yy0nHhHAP#OoezsfXjxs3NoJbuEDG7VRv56qrq9m3tmI5G8b+ZVy9epUbPCSQt2fG9pfu50ThwWyz3fYYtnC##3gqt8ewhS0R4jAKMufq7vkvy5O92S#5HMdxIaFhXGFhIdtsF49eEwOAyu0jEfac#WtNNy4fxZdfHkSpRoeTlUZ8V#M9vjt7BaEjHkD4Y48iJm4iRkWOc+jm89Cwkdard9qTlbUCSxQKttmjaXU6vJSagjOGjv#bO3Le9C22Hl6FQf0CkRL1Jn7p25#tQkiXGQwGxI2fgPj4qbRG5iBnrX8ZjUaEho0EAJyqrLB5osGs2XPw0YfbWvS2n0eviXWmwVyJsgP5WPn2fMyaHoVR4cEQPCiF#I13ceI7M56ekIgP8j7CrZsN+Prkt9j2912QyV9zKMBUqrxOAww836XYHQ8IR2Bx3BoAwJqSxfjp1o9sF0K6TCwWo6R4P4qK9iA#v4Atk044sv7VHpFIZA2uMy0+K5vu2Exr0bNrPD7E#ARhuHH5KBqvX0D1ic+w8b038UpSHEaFByMwaBRin30de4rLMDx0LNL#mI3Ll2px9lwtPt37ORRvZjjtVLll08aG3FzcutnQ5ssbzox1xy99++PV6HfwgPAhCjLiNJYgS1MoKMi6wBXnv4Y3h5jZ1PR0g1JN0+XQEknXnvhtg51f9CQHtFru1bmTOemYEG5oi3Ws115J4VSbNti1juUMZ86csd6T2JH21sw8XXV1Ndd3YF+2uVu2HFrJrfh0PnfjZj1bIsQhx48f5+69bzC3dWs+WyKM7q5#tceyLrZpk4q7evUqtyo7m+3SZR4zEjMYDFiXkwOZXI5RkaPh6+ePtDQFbtwRYuqMJHz6mQa3bjbg4GE9NnywBTL5a90a+naF5Z7EhOZt9e2x1C39+SIoKAiNDXecejtHStRSGpERp6IRWedcff+hUNB0FZ#J3HSnrDP2B#TKjR01NTXQanUwGAwwlBug032BYcOGQSwW43GxGNJoqdN#uKR7fP38ceLsEacfYF5TvBiD+g9BStRStkSIQyybPVYrlUhOTmLLXqvlJpjVSqVTpg9ZlssgYmNi8OGH26z3y3ZHj4eY2WyGTqeDwVAOrU4Lg6EcACAWhyNaGg2xOBxSqdQlP1DiPK4KsZ9u#Yj0XbORErUU4gefZMuEOESr02H8+AlQbdpEQda8#iWfPx9KZbZLr49SqfKgVquxd+9nbMlhbg8xrU4HnVaH4wYDDAYDzp49C6n0NxCHiyEWixEdLXXbNCBxHleFGAAYzh3E9rJcZEz5K229J05j+eAuLt7v1TM7MrkcRUV7UFi4wyN#Di4NMYPBAK2ueVrQUI7y8nKEh4dDLA5vCiyp1KHt7KT38fXzx+GvP8cTIVFsySnWFC#Gg#c8hJlPLGRLhDgsP78AaQoFSor3e91nkbPOf#U0p4UYrWN5t8ejHsfcV2fjdykdX5DsqCvXa5Gxaw7WzNxNozHiVK4KspvHjoCrq8et5ou#bx07AgDo86uh6DP0AQDA3UOHos#QofCLHGPzXldzx#qXuzgUYmazGYbycui0OlrHIgCAJ8ZJ8Ny8aVgq#wNbcpqth9#FoH6BeCY8hS0R0i3OCLKf6+tw45OduHnsKBo0JfAJDcMvBg6Eb3NA+YaNxF0DB6CxogI#19cDABorK3Dnwnk0nqqET2gY#EaPQd9nZ8Cn+WYLV3DX+pe72BVililBy0iL1rEIyx0hVnXJgA+0y7HmuSK2REi3ORpkN3btxE+lJWjQlMA#Jg6#jI2DX+QY9Blq#3MOf66vw62jR#FTaTEaNCXo86uh6J88F#6xcfjFgIFsd4d5+vpXWzoMsczMFchcsYLWsUin3BFiAJD12cuICUtA1PCJbImQbutKkN3YtRN1uTkAgIELU50aODd27cSNXTvRWFmBfklz0T85pVv#br6sf7WlwxCrqanh1X8scR13hZimUo2qSwa8Gv0OWyLEKSyjlfaCrLGyAtdWZuH2hQsYuDAVfZ#t+JKD7rh57Ajqc3PQWFkBYda78I+NY7t0ik#rX23p8MYOCjBir3uE9+DU6VNss9NFDZ8Iw#mDdIsHcZk8lQrx8VMhk8+H2Wy2qdXl5uBywjT4Ro5BYPHnLg0wAPCLHIN7t#wNwqx3YV6ZhSupC#BzffsPoGW54v7D3qbDECPEXo+Fh+P7i1fZZqf7pW9#PCB8CFWXDGyJEKfJU6kgFocjbvwEmM1m#Fxfhx#mvoiG0mIMVu#GwIXu3RDhHxuHwTt3AwAuz5iGxuYdjx2RyeVIUyhQXLyfFxs42kMhRjxOyBAxzjnxnkZC2mIJspjop3Fq7mz0+dVQ3Lv1by7dOdiRXwwYiEE5G9A#KQU#zH2x3SBz9f2HvQ2FGPE4DwhH4LzpO7aZEKfLU6kwYoAvnj+mx11vvtWtzRXO0j95LgL+J73NIHPm8788BYUY8TiD+gXiBq2JETf5+94ShAy5F09HSlqtkfWUvs#OaBVk3rD+1RYKMeIUd#e5223BMqj#EJy+TGtixD1+MWAgPt61F#f1+bnXBtlLySlesf7VFgox4hSPhjyG#xgvs80uMahfINtEiEv1GToUBR8V4ueGG5gWE82We8TP9XU4X7oPk2prYTAYvGL9qy0dnhMjxF5anQ4vpaZgXcEf2VKnHhSO6PJ9iO+VLMZf5pSyzYS4VO2#v8KE+Gfw+BOjkL#rH2zZbRorK#DPZb9HcvFBTJs+A++tW+s104csu0PM8jAzANYHmqVnZGBDbi7blfBEenoGCtVqGI1Ga5tcLoNcJoNEIrHpazabMXgIjZCc4dbNBraJ9CI9HWQNpSVQLl+Md8qqeHP#YbdwdigsLOR8fP241xYs4DiO486cOcOFhIZxy5als10JD1j+fn18#dp9rcrOZt9GiNe4qD#GPfbAEC5p2m#ZkktdW7+Om#boQ9w9AiF3QKtly17JrjWxM83fxCURTd++RSIR5HIZRCIR05PwwaTJU2A0GiGRSLAhNxe3bjbg1s0GXKq9CLlcBjSP0lSqPPathHiFwIhR2F#0Dxwv+wrJzz7Dlp3u5#o6VKW+jN9kr8TZu#pCf#zfXrn+1SY21dpSVlbG+fj6cSGhYdzVq1fZMuGRZcvSOR9fP27M2Ci2ZLUqO9v6#wMh3swdI7JbFd9we6ZP5IT9+3Nzk5I5k8nEdvFqdoUYx3Hcpk0q64cbBRl#WaYRS0pL2ZKNMWOjOB9fP66wsJAtEeJVKr74nBP07euSIPuppJjLjHqM8#H149auW8eWib3TiWhe0M#KWgG9Xo#Zs+ewZcIDRqMRRqMRQqEQsTExbNlGQkLTxaeWqWZCvFXYU09jr#pj7CnWIDdjKVt2WF1uDl743at4r+K8V57#sleHIVaq0Vh3JALAEoUCsTExKNVoUKrR2PQlns9kMgHNa56dEQqEQHPwEeLtxk56BrvfX4WM93K6HWS0#tU1HYaYXq+HXq+3aYuJbfqGbjxDH16EEGIhnf96c5CtR97aNWzZLo2VFfgs5TmM3fIRJNI4aHQ6r7j#sDs6DDGzyYxSjQbZSiXQ#E1dU6qBSCSyTicR#hAK7R9dmcz2j9oI8RZNQfYuFMuWdznIGkpL8O685zHj0wP445#+hM35W732AHNXdBhiJrMJl2ovwmg0wtfPH0MC7wcA7Nv7mfUDj#CHSCSCSCSCyWTqdLpYrd4JABhOIWa3Uo0Gvn7+bb4mT57CdiceypEgu7Yyi9a#HMXu9CDejbbYu85rCxa0OjTu4+vHvTBrNtuV8ID2rzmcj68fp3p#NVuyulN3jatIeYELD#oVF#HYY1x1dTXbhXSCQoy0YtlmP2ZsFLdpk8rafvXqVZsP4pY10rkXZs1udTyFbj7ht#Xpb3I+vn7cP7d#xJa4WxXfcEUTn6LzX91EIUZaoWun3GNVdjZ35swZtpnwzPr0NzlB377c4b17rG3XP1HT+S8nsfsCYOJ9unIBMOmabKUSiQkJtDHGS+RmLEXGe+uxV#0xRh43IGXbZnx5wQT1rk9o+3w3UYgR4mYqVR5iY2MowLzMmldS8E7BDgwWDED#++7HJ0W7afu8E1CIEeJGKlUeJJII60jWZDJBlZeHJQoF25Xw0Ob3VqHq4g9YumwZbZ93EgoxQtyEDTAAWLBwIRISEjq95osQ0jYKMULcQK1WY1Ybd44KhUJcqr3INhNC7NThYWdCSPepVHltBhgASCIi2CZCSBfQSIwQQojHopEYIYQQj0UhRgghbpCtVGLy5Cmt7s2cNXuO9ZJ10nU0nUgIIS5kNBoxa#acVo+1Yi1RKJCVtYJtJp2gkRghhLjQpMlToNfrIZFIkJW1ArduNti8srJWQC6XsW8jdqKRGCGEuEh6egaylUpIJBL86#AhtkycgEZihBDiIoVqNQDQNKEL0UiMEEJcwGg0IjRsJB1odzEaiRFCiAuYTCag+YnpLJPJ1GqXoq+fv#U9xH4UYoQQQjwWhRghhLiAUCgEmqcVWUKh0GaHoqUv6ToKMUIIcQGRSASRSASTyYRSjYYtEyehECOEEBexnP9KT89gS8RJKMQIIcRFligUkEgk0Ov1GBs1rs3rpdpqI#ajLfaEEOJC9l47tSE3l27ucACFGCGEuEG2UglNqcZmfUwkEiExIQEKRRpt7nAQhRghhBCP9X+LOy1T6KMGngAAAABJRU5ErkJgggAAAAEAAAAAAAAAAP####8AAAABAApDUG9pbnRCYXNlAP####8AAAD#P4AAAAAQAAAAQAgAAAAAAAAAAAAAAAAAAAAACAABQIAxHrhR64VAccrhR64Ue#####8AAAABABRDSW1wbGVtZW50YXRpb25Qcm90bwD#####AAdFcXVlcnJlAAAAEQAAAAYAAAABAAAAAv####8AAAACAAlDQ2VyY2xlT1IAAAAAAwEAAAA#gAAAAAAAAQAAAAIAAAABQHkAAAAAAAAB#####wAAAAEAFUNQb2ludEludGVyaWV1ckNlcmNsZQEAAAADAX8AAD+AAAAAEAAAAAAAAAAAAAAAQAgAAAAAAAAAAAkAAQAAAAQ#zri#JMnGxj+FVSLEyxkB#####wAAAAEACUNDZXJjbGVPQQAAAAADAQAAAD+AAAAAAAABAAAAAgAAAAX#####AAAAAQAPQ1BvaW50TGllQ2VyY2xlAQAAAAMAfwAAP4AAAAAQAAAAAAAAAAAAAABACAAAAAAAAAAAAwABQBkXbOjQ5PwAAAAG#####wAAAAEACENTZWdtZW50AAAAAAMBAAAAP4AAAAAQAAABAAAAAQAAAAcAAAAC#####wAAAAEAFkNEcm9pdGVQZXJwZW5kaWN1bGFpcmUAAAAAAwEAAAA#gAAAABAAAAEAAAABAAAAAgAAAAgAAAAHAAAAAAMBAAAAP4AAAAAAAQEAAAAHAAAAAv####8AAAABABBDSW50Q2VyY2xlQ2VyY2xlAAAAAAMAAAAGAAAACv####8AAAABABBDUG9pbnRMaWVCaXBvaW50AAAAAAMBAAAAP4AAAAAQAAAAAAAAAAAAAABACAAAAAAAAAAABQACAAAAC#####8AAAABAA1DRGVtaURyb2l0ZU9BAAAAAAMBAAAAP4AAAAAQAAABAAABAQAAAAcAAAAM#####wAAAAEAEENJbnREcm9pdGVEcm9pdGUBAAAAAwAAAAA#gAAAABAAAAAAAAAAAAAAAEAIAAAAAAAAAAAFAAAAAAkAAAAN#####wAAAAEADkNDZW50cmVHcmF2aXRlAAAAAAMBAAAAP4AAAAAQAAAAAAAAAAAAAABACAAAAAAAAAAABQAAAAAHAAAAAgAAAA7#####AAAAAQALQ0hvbW90aGV0aWUAAAAAAwAAAA######AAAAAQAKQ09wZXJhdGlvbgMAAAABP#AAAAAAAAAAAAABQAgAAAAAAAD#####AAAAAQALQ1BvaW50SW1hZ2UAAAAAAwEAAAA#gAAAABAAAAAAAAAAAAAAAEAIAAAAAAAAAAAFAAAAAAIAAAAQAAAAEgAAAAADAQAAAD+AAAAAEAAAAAAAAAAAAAAAQAgAAAAAAAAAAAUAAAAABwAAABAAAAASAAAAAAMBAAAAP4AAAAAQAAAAAAAAAAAAAABACAAAAAAAAAAABQAAAAAOAAAAEP####8AAAABAAlDUG9seWdvbmUBAAAAAwAAAAA#gAAAAAAAAQAAAAQAAAACAAAABwAAAA4AAAACAAAAEwEAAAADAAAAAD+AAAAAAAABAAAABAAAABEAAAASAAAAEwAAABH#####AAAAAQAOQ1BvaW50TGllTGlnbmUAAAAAAwEAAP8#gAAAAAsAAAAAAAAAAAAAAD#jMzMzMzMzAAACAAE#tg0mfKp9HwAAABUAAAAUAAAAAAMBAAD#P4AAAAALAAAAAAAAAAAAAAA#4zMzMzMzMwAAAgABP+mfEtMWCigAAAAU#####wAAAAIADUNMaWV1RGVQb2ludHMAAAAAAwEAAP8#gAAAAAAAAQAAABYAAADIAQAAAAAWAAAAAgAAABYAAAAWAAAAFQAAAAADAQAA#z+AAAAAAAABAAAAFwAAAMgBAAAAABcAAAACAAAAFwAAABf#####AAAAAQARQ1N1cmZhY2VEZXV4TGlldXgBAAAAAwC9vb0+TMzNAAAAAAAFAAAAGAAAABn#####AAAAAwAMQ0NvbW1lbnRhaXJlAP####8AAAAAP4AAAAEAAP####8SQDIAAAAAAABALgAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAABADRFbiB1dGlsaXNhbnQgbCfDqXF1ZXJyZSwgZG9ubmUgbGEgbmF0dXJlIGRlcyBhbmdsZXMuAAAAAP####8AAAADAAZDTGF0ZXgA#####wAAAAA#gAAAAQAA#####xRAPwAAAAAAAEB2QAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAEBHVxiZWdpbnthcnJheX17fGN8Y3xjfGN8fQpcaGxpbmUKXGNvbHVtbmNvbG9ye2xpZ2h0Y3lhbn1cdGV4dHtBbmdsZX0gJiBcLFwsXCxcbWF0aHJte1x3aWRlaGF0e3JBc319XCxcLFwsICYgXCxcLFwsXG1hdGhybXtcd2lkZWhhdHt6T3d9fVwsXCxcLCAmIFwsXCxcLFx3aWRlaGF0e1xtYXRocm17SFBJfVwsXCxcLH0KJiBcLFwsXCxcbWF0aHJte1x3aWRlaGF0e3VHdn19XCxcLFwsClxcIFxobGluZQpcdGV4dHtOYXR1cmV9ICYgLi4uICYgLi4uICYgLi4uICYgLi4uClxcIFxobGluZQpcZW5ke2FycmF5fQAAAAAAAAAXAP####8AfwB#P4AAAAEAAP####8PQEKAAAAAAABAfSAAAAAAAAIAAAAAAAAAAAAAAAABAAAAAAAAAAABAGFQb3VyIGTDqXBsYWNlciBsJ8OpcXVlcnJlLCBjYXB0dXJlIGxlIHBvaW50IGJsZXUuClBvdXIgbGEgZmFpcmUgdG91cm5lciwgY2FwdHVyZSBsZSBwb2ludCBtYXJyb24uAAAAAP###############w==
    addTypeset(g)
    if (this.cbmap) this.resetEventListeners() // Ajout version 6.5.2
  } else {
    this.positionneAngText(this.g)
  }
  // Ajout version 5.0.1
  if ((this.pointLie !== null) && !this.pointLie.dansFenetre) {
    this.g.setAttribute('visibility', 'hidden')
  } else {
    this.g.setAttribute('visibility', 'visible')
  }
}

CLatex.prototype.parametres = function (nbArg, ch, debut, fin) {
  let i, j, codePar, indsuiv
  indsuiv = -1
  const len = ch.length
  // On remplace les retours chariot par des espaces
  // Non il ne faut pas remplacer les retours chariots par des espaces car pour le LaTeX cela revient
  // à rajouter des espaces et pour les affichages de texte ce n'est pas anodin.
  // ch = ch.replace(/\n/g, ' ')
  let chtest = ch
  // On remplace dans ch tous les \\left{ et \\right} pas des espaces car ce sont pas
  // de vraies accolades en respectant le même nombre de caractères (8 pour \right\{ et 7 pour \left\{)
  chtest = chtest.replace(/\\right\\}/g, ' '.repeat(8)).replace(/\\left\\{/g, ' '.repeat(7))
  const chret = new Array(nbArg)
  i = debut
  for (j = 0; j < nbArg; j++) {
    if (i >= len) return null
    if (chtest.substring(i).trim().charAt(0) !== '{') {
      return null
    }
    codePar = 1
    const indparouvdeb = chtest.substring(i).indexOf('{')
    i += indparouvdeb + 1
    indsuiv = i
    let deb = chtest.substring(i)
    let indpar
    while (((indpar = deb.search(/[{}]/g)) !== -1) && codePar > 0) {
      const cardeb = deb.charAt(indpar)
      if (cardeb === '{') {
        codePar++
      } else {
        codePar--
        if (codePar < 0) return null
      }
      deb = deb.substring(indpar + 1)
      indsuiv += indpar + 1
    }
    if (codePar !== 0) return null
    chret[j] = ch.substring(i, indsuiv - 1)
    i = indsuiv
  }
  fin.setValue(indsuiv - 1)
  return chret
}
/**
 * Fonction traitant les codes LaTeX spécifiques à MathGraph32.
 * Pour plus de renseignements sur ces codes spéciaux, voir l'aide en ligne dans MathGraph32 (appuyer sur F1).
 * @param {string} ch  La chaîne contenant les codes.
 * @returns {string}
 */
CLatex.prototype.traiteCodesLatex = function (ch) {
  let ideb, param, chremp
  const fin = new Pointeur(0)
  // Les codes \If peuvent être imbriqués les uns dans les autres. Il faut les rechecher tant
  // qu'il y en a et les traiter depuis le début.
  while ((ideb = ch.indexOf('\\If', 0)) !== -1) {
    param = this.parametres(3, ch, ideb + 3, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('If')
      break
    } else {
      chremp = this.traiteCodeIf(param)
      ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
    }
  }
  // Ajout version 6.7. Traitement des codes \ValFrac. A faire impérativement avant les \Val
  // Renvoie la fraction continue équivalente au résultat de l'argument à 10^(-12) près
  while ((ideb = ch.indexOf('\\ValFrac', 0)) !== -1) {
    param = this.parametres(1, ch, ideb + 8, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('ValFrac')
      break
    }
    chremp = this.traiteCodeValFrac(param[0].trim())
    ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
  }
  // Traitement des codes \Val
  while ((ideb = ch.indexOf('\\Val', 0)) !== -1) {
    param = this.parametres(1, ch, ideb + 4, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('Val')
      break
    } else {
      chremp = ''
      try {
        chremp = this.traiteCodeVal(param[0].trim())
        ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
      } catch (e) {
        ch = ch.substring(0, ideb) + codeErreur('Val')
      }
    }
  }
  // Ajout version 7.3 : Traitement des codes \Decomp et \DecompFull
  const tab = ['\\DecompFull', '\\Decomp'] // Ordre important il faut commencer par le plus long
  for (let k = 0; k < 2; k++) {
    while ((ideb = ch.indexOf(tab[k], 0)) !== -1) {
      param = this.parametres(1, ch, ideb + tab[k].length, fin)
      if (param === null) {
        ch = ch.substring(0, ideb) + codeErreur('Decomp')
        break
      } else {
        chremp = ''
        try {
          chremp = this.traiteCodeDecomp(param[0], k === 0)
          ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
        } catch (e) {
          ch = ch.substring(0, ideb) + codeErreur('Decomp')
        }
      }
    }
  }
  // Traitement des codes \FracRed
  while ((ideb = ch.indexOf('\\FracRed', 0)) !== -1) {
    param = this.parametres(1, ch, ideb + 8, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('FracRed')
      break
    }
    chremp = this.traiteCodeFracRed(param[0])
    ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
  }
  // Version 6.7 : Traitement des codes \ForSimpFrac. A faire impérativement avant les \For
  // Fonctionne comme les \ForSimp sauf que les valeurs non entières sont remplacées par
  // des fractions correspondant à la fraction continue équivalente à 10^(-12) près
  while ((ideb = ch.indexOf('\\ForSimpFrac', 0)) !== -1) {
    param = this.parametres(1, ch, ideb + 12, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('ForSimpFrac')
      break
    }
    chremp = this.traiteCodeForSimpFrac(param[0].trim())
    ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
  }

  // Traitement des codes \ForSimp. A faire impérativement avant les \For
  while ((ideb = ch.indexOf('\\ForSimp', 0)) !== -1) {
    param = this.parametres(1, ch, ideb + 8, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('ForSimp')
      break
    }
    chremp = this.traiteCodeForSimp(param[0].trim())
    ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
  }
  // Traitement des codes \ForRep. A faire impérativement avant les \For
  while ((ideb = ch.indexOf('\\ForRep', 0)) !== -1) {
    param = this.parametres(1, ch, ideb + 7, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('ForRep')
      break
    }
    chremp = this.traiteCodeForRep(param[0].trim())
    ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
  }
  // Traitement des codes \For
  while ((ideb = ch.indexOf('\\For', 0)) !== -1) {
    param = this.parametres(1, ch, ideb + 4, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('For')
      break
    }
    chremp = this.traiteCodeFor(param[0].trim())
    ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
    ideb = fin.getValue() + 1
  }
  // Traitement des codes \CalcSimp. A faire impérativement avant les \Calc
  while ((ideb = ch.indexOf('\\CalcSimp', 0)) !== -1) {
    param = this.parametres(1, ch, ideb + 9, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('CalcSimp')
      break
    }
    chremp = this.traiteCodeCalcSimp(param[0])
    ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
  }
  // Traitement des codes \Calc
  while ((ideb = ch.indexOf('\\Calc', 0)) !== -1) {
    param = this.parametres(1, ch, ideb + 5, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('Calc')
      break
    }
    chremp = this.traiteCodeCalc(param[0])
    ch = ch.substring(0, ideb) + chremp + ch.substring(fin.getValue() + 1)
  }
  // Version 8.8 : On regarde s'il y a des codes \Lat pour insérer le code LaTeX
  // d'un affichage défini avant le code LaTeX étant \Lat{tag} où tag est le tag
  // de l'affichage LaTeX dont le code est à réutiliser
  // Version 8.8 (n° de version 22) : traitement des codes \Lat{tag}
  // qui remplacent par le code LaTeX renvoyé par l'affichage LaTeX de tag tag
  // à condition que cet affichage LaTeX soit défini avant
  const list = this.listeProprietaire
  while ((ideb = ch.indexOf('\\Lat', 0)) !== -1) {
    const param = this.parametres(1, ch, ideb + 4, fin)
    if (param === null) {
      ch = ch.substring(0, ideb) + codeErreur('Lat')
      break
    }
    const indfin = fin.getValue()
    const index = this.index
    // Si this.index est égal à -1 c'est qu'on est en train de créer un nouveau LaTeX
    // provisoire dans l'aperçu de la boîte de dialogue d'édition de LaTeX
    const lat = list.getLaTeXByTagBefore(param[0], index === -1 ? list.longueur() : index)
    if (lat === null) {
      ch = ch.substring(0, ideb) + codeErreur('Lat') + ch.substring(indfin + 1)
    } else {
      const remp = lat.existe ? lat.chaineLatex : ''
      ch = ch.substring(0, ideb) + ' ' + remp + ' ' + ch.substring(indfin + 1)
    }
  }
  return ch
}
/**
 * Fonction traitant les codes \Val permettant d'insérer la représentation décimale
 * d'un calcul réel ou complexe ou d'une variable dans l'affichage.
 * @param {string[]} param  Tableau de chaînes contenant les codes.
 * @returns {string} : La chaîne traitée.
 */
CLatex.prototype.traiteCodeVal = function (param) {
  // On sépare cette chaine avec les virgules
  let nomvaleur, indfin, pValeur, chnbdec, nbdecimales, chplus, signePlusImpose, nombre
  let chnombre = ''
  const st = param.split(/\s*,\s*/)
  if (st.length !== 0) {
    nomvaleur = st[0]
    indfin = this.listValDynUsed.longueur() - 1
    pValeur = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValPourComDynSaufFonc, nomvaleur, indfin)
    if (pValeur !== null) {
      // Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
      if (pValeur.existe) {
        if (pValeur.estMatrice()) {
          if (st.length >= 2) chnbdec = st[1]
          else chnbdec = '2'
          nbdecimales = parseInt(chnbdec.trim())
          chnombre = pValeur.latexMat(nbdecimales)
        } else {
          if (st.length >= 2) {
            chnbdec = st[1]
            if (chnbdec === '+') {
              chnombre = pValeur.rendChaineValeurPourCommentaire(2)
              if (chnombre.indexOf('-') === 0) chnombre = ' -' + chnombre.substring(1)
              else chnombre = ' +' + chnombre
            } else {
              // On retire les espaces de début
              chnbdec = chnbdec.trim()
              nbdecimales = parseInt(chnbdec)
              chnombre = pValeur.rendChaineValeurPourCommentaire(nbdecimales)
              // Si le troisième paramètre :
              // commence par + : on impose un signe + devant l'affichage si le nombre est positif ou nul
              // finit par un zéro : on impose un signe + devant l'affichage si le nombre est positif ou nul
              // et on n'affiche rien si le nombre est nul
              // finit par 1 : on n'affiche pas le nombre si le nombre est égal à 1 et on affiche un signe - sil est égal à -1
              if (st.length >= 3) {
                chplus = st[2]
                // On retire les éventuels espaces de début
                chplus = chplus.trim()
                signePlusImpose = chplus.indexOf('+') === 0
                if (signePlusImpose) {
                  if (chnombre.indexOf('-') === -1) chnombre = '+' + chnombre
                }
                if (chplus.indexOf('0') === chplus.length - 1) {
                  nombre = pValeur.rendValeur()
                  if (nombre === 0) return ' '
                } else {
                  nombre = pValeur.rendValeur()
                  if (chplus.indexOf('1') === chplus.length - 1) {
                    if (nombre === 1) return signePlusImpose ? '+' : ' '
                    else if (nombre === -1) return '-'
                  }
                }
              }
            }
          } else {
            // Si le nombre de décimales n'est pas précisé, on en met deux par défaut
            return pValeur.rendChaineValeurPourCommentaire(2)
          }
        }
      }
    }
  } else return codeErreur('Val')
  return chnombre
}
CLatex.prototype.traiteCodeValFrac = function (param) {
  let chnombre = ''
  const st = param.split(/\s*,\s*/)
  if (st.length !== 0) {
    const nomvaleur = st[0]
    const indfin = this.listValDynUsed.longueur() - 1
    const pValeur = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValPourComDynSaufFoncSaufComp, nomvaleur, indfin)
    if (pValeur !== null) {
      if (pValeur.existe) {
        // Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
        if (pValeur.estMatrice()) {
          return pValeur.latexMatFrac()
        } else {
          const res = pValeur.rendValeur()
          if (res === Math.floor(res)) chnombre = String(res)
          else {
            chnombre = codeLatexFracCont(fracCont(res))
          }
          if (st.length >= 2) {
            let chplus = st[1]
            // On retire les éventuels espaces de début
            chplus = chplus.trim()
            const signePlusImpose = chplus.indexOf('+') === 0
            if (signePlusImpose) {
              if (chnombre.indexOf('-') === 0) chnombre = ' -' + chnombre.substring(1)
              else chnombre = ' +' + chnombre
            }
            if (chplus.indexOf('0') === chplus.length - 1) {
              if (res === 0) return ' '
            } else {
              if (chplus.indexOf('1') === chplus.length - 1) {
                if (res === 1) return signePlusImpose ? ' + ' : ' '
                else if (res === -1) return ' - '
              }
            }
          }
        }
      }
    } else return codeErreur('ValFrac')
  } else return codeErreur('ValFrac')
  return chnombre
}

/**
 * Fonction traitant les codes \Decomp et \DecompFull et qui fournit la décomposition en produit de facteurs premiers
 * d'un entier au moins égal à 2
 * @param{string} param Doit contenir la nom de la valeur réelle à décomposer
 * @param {boolean} bfull Si true, on répète les facteurs au lieu de mettre des exposants
 * @returns {string}
 */
CLatex.prototype.traiteCodeDecomp = function (param, bfull) {
  let chnombre = ''
  const st = param.split(/\s*,\s*/)
  if (st.length !== 0) {
    const nomvaleur = st[0]
    const indfin = this.listValDynUsed.longueur() - 1
    const pValeur = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValRPourComDyn, nomvaleur, indfin)
    if (pValeur !== null) {
      if (pValeur.existe) {
        // Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
        const res = pValeur.rendValeur()
        if (!zero(res - Math.round(res)) || (res > 10000000)) return chaineNombre(res, 12)
        const nb = Math.round(res)
        const neg = nb < 0
        const absnb = Math.abs(nb)
        if (absnb === 1 || nb === 0) return String(nb)
        const decomp = decompPrim(Math.round(absnb)) // Tableau dont le premier élélent est un tableau contenant les facteurs premiers
        // et le second un tableau contenant les exposants
        const factprem = decomp[0]
        const expo = decomp[1]
        const nbfactprem = factprem.length
        if (bfull) {
          let nbfact = 0
          for (let i = 0; i < nbfactprem; i++) {
            for (let k = 0; k < expo[i]; k++) {
              nbfact++
              if (nbfact !== 1) chnombre += '\\times'
              chnombre += String(factprem[i])
            }
          }
        } else {
          for (let i = 0; i < nbfactprem; i++) {
            if (i !== 0) chnombre += '\\times '
            chnombre += String(factprem[i]) + '^{' + String(expo[i]) + '}'
          }
        }
        if (neg) chnombre = '-' + chnombre
      }
    } else return codeErreur('Decomp')
  } else return codeErreur('Decomp')
  return chnombre
}

/**
 * Fonction traitant les codes \FracRed permettant d'insérer une fraction
 * qui est la fraction réduite représentant un quotient de deux entiers.
 * @param {string[]} param  Tableau de chaînes contenant les codes..
 * @returns {string} : La chaîne traitée.
 */
CLatex.prototype.traiteCodeFracRed = function (param) {
  let nomvaleur1, indfin, pValeurNum, num, nomvaleur2, pValeurDen, den, numabs, denabs, signePlusImpose, chsig, g, num1, den1, positif
  // On sépare cette chaine avec les virgules
  let res = ' '
  const st = param.split(/\s*,\s*/)
  if (st.length !== 0) {
    nomvaleur1 = st[0]
    // On recherche si c'est bien le nom d'une valeur valide
    // Il ne faut pas que la valeur ait été définie après l'affichage de valeur
    // Si c'est le nom d'une valeur utilisée, elle est comprise dans la
    // liste listValDynUsed
    indfin = this.listValDynUsed.longueur() - 1
    pValeurNum = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValRPourComDyn, nomvaleur1, indfin)
    if (pValeurNum === null) return codeErreur('FracRed')
    if (pValeurNum.existe) {
      num = pValeurNum.rendValeur(false)
      if (st.length >= 2) {
        nomvaleur2 = st[1]
        pValeurDen = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValRPourComDyn, nomvaleur2, indfin)
        if (pValeurDen === null) return codeErreur('FracRed')
        if (pValeurDen.existe) {
          den = pValeurDen.rendValeur()
          if (den === 0) return codeErreur('FracRed')
          numabs = Math.abs(num)
          denabs = Math.abs(den)
          if ((numabs !== Math.floor(numabs)) || (numabs > MAX_VALUE) ||
            (denabs !== Math.floor(denabs)) || (denabs > MAX_VALUE) || (denabs === 0)) return codeErreur('FracRed')
          else {
            signePlusImpose = false
            chsig = ''
            if (st.length >= 3) {
              chsig = st[2]
              if (chsig.indexOf('+') === 0) signePlusImpose = true
            }
            if ((num === 0) && (chsig !== '') && (chsig.charAt(chsig.length - 1) === '0')) return ' '
            g = pgcd(numabs, denabs)
            num1 = numabs / g
            den1 = denabs / g
            positif = (num * den >= 0)
            if (zero13(den1 - 1)) {
              if (zero13(num1 - 1) && (chsig !== '') && (chsig.charAt(chsig.length - 1) === '1')) {
                if (positif) return signePlusImpose ? ' + ' : ' '
                else return ' - '
              }
              res = chaineNombre(num1, 0)
            } else res = ' \\dfrac{' + chaineNombre(num1, 0) + '}{' + chaineNombre(den1, 0) + '} '
            if (positif && signePlusImpose) res = ' +' + res
            else { if (!positif) res = ' -' + res }
            // Abandonné car on utilise des \dfrac partout : Modification version 6.4. On utilise displaystyle sinon trop petit avec MathJax3
            // return '\\displaystyle ' + res
            return res
          }
        }
      }
    }
  }
  return res
}
/**
 * Fonction traitant les codes \If permettant d'avoir un affichage conditionnel
 * La syntaxe est \If{Test}{Affichage si 1}{Affichage sinon}
 * @param {string} param  Tableau de chaînes contenant les codes.
 * @returns {string} : La chaîne égale au résultat du test .
 */
CLatex.prototype.traiteCodeIf = function (param) {
  let num
  const indfin = this.listValDynUsed.longueur() - 1
  // Modifié version 4.7.2
  // CValDyn pValeurNum = latex.listValDynUsed.pointeurValeurOuFonction(nomvaleur,indfin);
  const pValeurNum = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValPourComDynSaufFonc, param[0], indfin)
  if (pValeurNum === null) return codeErreur('If')
  if (pValeurNum.existe) {
    if (pValeurNum.getNatureCalcul() === NatCal.NCalculComplexe) {
      const z = new Complexe()
      pValeurNum.rendValeurComplexe(z)
      if ((z.x === 1) && (z.y === 0)) return param[1]; else return param[2]
    } else {
      if (pValeurNum.estDeNatureCalcul(NatCal.NTteValRPourComDyn)) {
        num = pValeurNum.rendValeur()
        if (num === 1) return param[1]; else return param[2]
      } else return param[2]
    }
  } else return param[2]
}
/**
 * Fonction traitant les codes \For permettant d'obtenir le codeLaTex d'un calcul ou une fonction.
 * Les calculs ou variables utilisés dans la fonction ne sont pas remplacés par leur valeur.
 * La syntaxe est \For{a} où a est le nom d'une calcul ou d'une fonction.
 * @param {string} param  La chaîne à traiter.
 * @returns {string} : La chaîne contenant le code LaTeX.
 */
CLatex.prototype.traiteCodeFor = function (param) {
  const indfin = this.listValDynUsed.longueur() - 1
  const calcul = this.listValDynUsed.pointeurParNatureCalcul(Nat.or(NatCal.NCalcouFoncParFormule, NatCal.NMatrice), param, indfin)
  if (calcul !== null) {
    if (calcul.className === 'CMatrice') {
      const n = calcul.n
      const p = calcul.p
      let res = '\\begin{matrix}'
      for (let i = 0; i < n; i++) {
        if (i !== 0) res += '\\\\'
        for (let j = 0; j < p; j++) {
          if (j !== 0) res += ' & '
          const val = calcul.tabVal[i][j]
          res += val.calcul.chaineLatexSansPar(null)
        }
      }
      return res + '\\end{matrix}'
    } else {
      const varFor = calcul.variableFormelle()
      return calcul.calcul.chaineLatexSansPar(varFor)
    }
  } else return codeErreur('For')
}
/**
 * Fonction traitant les codes \Calc permettant d'afficher la formule d'un calcul ou une fonction
 * Cette formule est rénvoyée telle qu'elle serait écrite (avec les signes * de multiplication).
 * Le code renvoyé n'est pas un code LaTeX.
 * Les calculs ou variables utilisés dans la formule ne sont pas remplacés par leur valeur.
 * La syntaxe est \Calc{a} où a est le nom d'une calcul ou d'une fonction.
 * @param {string} param  La chaîne contenant les codes.
 * @returns {string} : La chaîne contenant la formule.
 */
CLatex.prototype.traiteCodeCalc = function (param) {
  let varFor, nbv, k, chret, stb, i
  const indfin = this.listValDynUsed.longueur() - 1
  const calcul = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValPourComDyn, param, indfin)
  if (calcul !== null) {
    varFor = null
    if (calcul.estDeNatureCalcul(Nat.or(NatCal.NFonction, NatCal.NFonctionComplexe))) {
      varFor = new Array(1)
      varFor[0] = calcul.nomsVariables
    } else {
      if (calcul.estDeNatureCalcul(Nat.or(NatCal.NFoncPlusieursVar, NatCal.NFoncCPlusieursVar))) {
        nbv = calcul.nbVar
        varFor = new Array(nbv)
        for (k = 0; k < nbv; k++) varFor[k] = calcul.nomsVariables[k]
      }
    }
    // chret = "\\text{" + calcul.calcul.chaineCalculSansPar(varFor) + "}"; //.Modifié version 4.9.2.3
    chret = calcul.calcul.chaineCalculSansPar(varFor)
    // Il faut remplacer les caractères ^ par \^{}
    stb = chret
    for (i = 0; i < stb.length; i++) {
      if (stb.charAt(i) === '^') {
        // stb.replace(i, i+1, "\\;\\^{}\\;");
        // stb = stb.substring(0, i-1) + "\\;\\^{}\\;" + stb.substring(i+1); //.Modifié version 4.9.2.3
        stb = stb.substring(0, i) + ' \\;\\widehat{\\;\\;}\\; ' + stb.substring(i + 1)
        i = i + 8
      }
    }
    return stb.toString()
  } else return codeErreur('Calc')
}
/**
 * Fonction traitant les codes \Calc permettant d'afficher la formule d'un calcul ou une fonction
 * Cette formule est rénvoyée telle qu'elle serait écrite (avec les signes * de multiplication).
 * Le code renvoyé n'est pas un code LaTeX.
 * Les calculs ou variables utilisés dans la formule sont remplacés par leur valeur.
 * L'expression du calcul est simplifiée le plus possible (par exemple les termes nuls d'une somme
 * ne sont pas écrits, 1*x est remplacé par x).
 * La syntaxe est \Calc{a} où a est le nom d'une calcul ou d'une fonction.
 * @param {string} param  La chaîne contenant les codes.
 * @returns {string} : La chaîne contenant la formule.
 */
CLatex.prototype.traiteCodeCalcSimp = function (param) {
  let varFor, chret, stb, i
  const indfin = this.listValDynUsed.longueur() - 1
  const calcul = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValPourComDyn, param.toString(), indfin)
  if (calcul !== null) {
    varFor = calcul.variableFormelle()
    chret = '\\text{' + calcul.calcul.calculAvecValeursRemplacees(false)
      .calculNormalise(true, false, false).chaineCalculSansPar(varFor) + '}'
    // Il faut remplacer les caractères ^ par \^{}
    stb = chret
    for (i = 0; i < stb.length; i++) {
      if (stb.charAt(i) === '^') {
        stb = stb.substring(0, i - 1) + '\\;\\^{}\\;' + stb.substring(i + 1)
        i = i + 8
      }
    }
    return stb.toString()
  } else return codeErreur('CalcSimp')
}
/**
 * Fonction traitant les codes \ForSimp permettant d'obtenir le codeLaTex d'un calcul ou une fonction.
 * Les calculs ou variables utilisés dans la fonction sont remplacés par leur valeur décimale.
 * L'expression du calcul est simplifiée le plus possible (par exemple les termes nuls d'une somme
 * ne sont pas écrits, 1*x est remplacé par x).
 * La syntaxe est \ForSimp{a} où a est le nom d'une calcul ou d'une fonction.
 * @param {string} param  La chaîne à traiter.
 * @returns {string} : La chaîne contenant le code LaTeX.
 */

CLatex.prototype.traiteCodeForSimp = function (param) {
  let varFor
  const indfin = this.listValDynUsed.longueur() - 1
  const calcul = this.listValDynUsed.pointeurParNatureCalcul(Nat.or(NatCal.NCalcouFoncParFormule, NatCal.NMatrice), param, indfin)
  if (calcul !== null) {
    if (calcul.className === 'CMatrice') {
      const n = calcul.n
      const p = calcul.p
      let res = '\\begin{matrix}'
      for (let i = 0; i < n; i++) {
        if (i !== 0) res += '\\\\'
        for (let j = 0; j < p; j++) {
          if (j !== 0) res += ' & '
          const val = calcul.tabVal[i][j]
          res += val.calcul.calculAvecValeursRemplacees(false).calculNormalise(true, false, false).chaineLatexSansPar(null)
        }
      }
      return res + '\\end{matrix}'
    }
    varFor = calcul.variableFormelle()
    // return calcul.calcul.calculAvecValeursRemplacees().calculNormalise(true, false, false).chaineLatexSansPar(varFor);
    // Abandonné car on utilise des \dfrac partout : Modification version 6.4 pour que le résultat avec MathJax3 soit équivalent à celui de l'ancienne version de MathJax
    // return '\\displaystyle ' + calcul.calcul.calculAvecValeursRemplacees(false).calculNormalise(true, false, false).chaineLatexSansPar(varFor)
    return calcul.calcul.calculAvecValeursRemplacees(false).calculNormalise(true, false, false).chaineLatexSansPar(varFor)
  } else return codeErreur('ForSimp')
}
/**
 * Fonction traitant les codes \ForRep permettant d'obtenir le codeLaTex d'un calcul ou une fonction.
 * Les calculs ou variables utilisés dans la fonction sont remplacés par leur valeur décimale.
 * Contrairement au code \ForSimp les multiplications ou divisions par 1, -1 et les sommes avec 0
 * ne sont pas simplifiées
 * La syntaxe est \ForRep{a} où a est le nom d'une calcul ou d'une fonction.
 * @param {string} param  La chaîne à traiter.
 * @returns {string} : La chaîne contenant le code LaTeX.
 */

CLatex.prototype.traiteCodeForRep = function (param) {
  let varFor
  const indfin = this.listValDynUsed.longueur() - 1
  const calcul = this.listValDynUsed.pointeurParNatureCalcul(Nat.or(NatCal.NCalcouFoncParFormule, NatCal.NMatrice), param, indfin)
  if (calcul !== null) {
    if (calcul.className === 'CMatrice') {
      const n = calcul.n
      const p = calcul.p
      let res = '\\begin{matrix}'
      for (let i = 0; i < n; i++) {
        if (i !== 0) res += '\\\\'
        for (let j = 0; j < p; j++) {
          if (j !== 0) res += ' & '
          const val = calcul.tabVal[i][j]
          res += val.calcul.calculAvecValeursRemplacees(false).chaineLatexSansPar(null)
        }
      }
      return res + '\\end{matrix}'
    }
    varFor = calcul.variableFormelle()
    // return calcul.calcul.calculAvecValeursRemplacees().calculNormalise(true, false, false).chaineLatexSansPar(varFor);
    // Abandonné car on utilise des \dfrac partout : Modification version 6.4 pour que le résultat avec MathJax3 soit équivalent à celui de l'ancienne version de MathJax
    // return '\\displaystyle ' + calcul.calcul.calculAvecValeursRemplacees(false).calculNormalise(true, false, false).chaineLatexSansPar(varFor)
    return calcul.calcul.calculAvecValeursRemplacees(false).chaineLatexSansPar(varFor)
  } else return codeErreur('ForSimp')
}
/**
 * Fonction traitant les codes \For permettant d'obtenir le codeLaTex d'un calcul ou une fonction.
 * Les calculs ou variables utilisés dans la fonction sont remplacés par leur valeur s'ils
 * prennent une valeur entière et par une fraction continue équivalente à 10^(-12) sinon.
 * L'expression du calcul est simplifiée le plus possible (par exemple les termes nuls d'une somme
 * ne sont pas écrits, 1*x est remplacé par x).
 * La syntaxe est \For{a} où a est le nom d'une calcul ou d'une fonction.
 * @param {string} param  La chaîne à traiter.
 * @returns {string} : La chaîne contenant le code LaTeX.
 */

CLatex.prototype.traiteCodeForSimpFrac = function (param) {
  let varFor
  const indfin = this.listValDynUsed.longueur() - 1
  const calcul = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValPourComDyn, param, indfin)
  if (calcul !== null) {
    if (calcul.estMatrice()) {
      if (calcul.className === 'CMatrice') {
        const n = calcul.n
        const p = calcul.p
        let res = '\\begin{matrix}'
        for (let i = 0; i < n; i++) {
          if (i !== 0) res += '\\\\'
          for (let j = 0; j < p; j++) {
            if (j !== 0) res += ' & '
            const val = calcul.tabVal[i][j]
            // Ici calculAvecValeursRemplacees remplace les valeurs par leur fraction continue approchée à 10^(-12) près
            res += val.calcul.calculAvecValeursRemplacees(true).calculNormalise(true, false, true).chaineLatexSansPar(null)
          }
        }
        return res + '\\end{matrix}'
      } else return codeErreur('ForSimp')
    }
    varFor = calcul.variableFormelle()
    // return calcul.calcul.calculAvecValeursRemplacees().calculNormalise(true, false, false).chaineLatexSansPar(varFor);
    // Abandonné car on utilise des \dfrac partout : Modification version 6.4 pour que le résultat avec MathJax3 soit équivalent à celui de l'ancienne version de MathJax
    // return '\\displaystyle ' + calcul.calcul.calculAvecValeursRemplacees(true).calculNormalise(true, false, false).chaineLatexSansPar(varFor)
    return calcul.calcul.calculAvecValeursRemplacees(true).calculNormalise(true, false, true).chaineLatexSansPar(varFor)
  } else return codeErreur('ForSimp')
}

/*
CLatex.prototype.read = function(inps, list){
  CCommentaire.prototype.read.call(this, inps, list);
};
*/

/**
 * Fonction remplaçant dans this.commentairre les appels dynamiques de calcul,
 * fonction ou variable nommé ancienNom par nouveauNom.
 * @param {string} ancienNom
 * @param {string} nouveauNom
 * @returns {boolean} : la chaîne traitée.
 */
CLatex.prototype.remplaceNomValeurDynamique = function (ancienNom, nouveauNom) {
  // On supprime d'abord tous les caractères espace suivant un { ou une virgule ou précédant une accolade
  let buffer = this.chaineCommentaire
  const chaineInitiale = buffer
  // Ajout version 6.7 : Traitement des codes \ValFrac
  let ch1 = '\\\\ValFrac{[ ]*' + ancienNom + '[ ]*\\}'
  let ch2 = '\\ValFrac{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)

  ch1 = '\\\\Val\\{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\Val{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)

  // Ajout version 7.3 pour le nouveau code \DecompFull
  ch1 = '\\\\DecompFull\\{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\DecompFull{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)

  // Ajout version 7.3 pour le nouveau code \Decomp
  ch1 = '\\\\Decomp\\{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\Decomp{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)

  ch1 = '\\\\Val{[ ]*' + ancienNom + '[ ]*,'
  ch2 = '\\Val{' + nouveauNom + ','
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
  ch1 = '\\\\For{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\For{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
  // Version 6.7 : traitement des nouveaux codes \SimpFor
  ch1 = '\\\\ForSimpFrac{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\ForSimpFrac{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
  ch1 = '\\\\ForSimp{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\ForSimp{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
  ch1 = '\\\\ForRep{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\ForRep{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
  ch1 = '\\\\Calc{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\Calc{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
  ch1 = '\\\\CalcSimp{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\CalcSimp{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
  ch1 = '\\\\FracRed{[ ]*' + ancienNom + '[ ]*,'
  ch2 = '\\FracRed{' + nouveauNom + ','
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
  ch1 = '\\\\If{[ ]*' + ancienNom + '[ ]*\\}'
  ch2 = '\\If{' + nouveauNom + '}'
  buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
  this.chaineCommentaire = buffer
  this.remplaceNomValeurDynamiqueApresVirgule('\\FracRed{', ancienNom, nouveauNom)
  return (chaineInitiale !== this.chaineCommentaire)
}
/**
 * Fonction recherchant dans les codes spéciaux utilisant une virgue ancienNom et le replaçant par nouveauNom.
 * @param {string} code  contient  \FracRed qui est pour le moment le seul code avec virgules
 * dont le deuxième argument peut être le nom d'un calcul ou une variable.
 * @param {string} ancienNom  Le nom de calcul, variable ou fonction à remplacer.
 * @param {string} nouveauNom  Le nom du calcul, variable ou fonction qui remplace.
 * @returns {void}
 */
CLatex.prototype.remplaceNomValeurDynamiqueApresVirgule = function (code, ancienNom, nouveauNom) {
  let ind = 0
  while ((ind = this.chaineCommentaire.indexOf(code, ind)) !== -1) {
    // On recherche la première accolade fermante
    const indacf = this.chaineCommentaire.indexOf('}', ind + code.length)
    if (indacf !== -1) {
      const left = this.chaineCommentaire.substring(0, ind + code.length - 1)
      const right = this.chaineCommentaire.substring(indacf + 1)
      let mid = this.chaineCommentaire.substring(ind + code.length - 1, indacf + 1)
      let ch1 = ',' + ancienNom + ' '
      let ch2 = ',' + nouveauNom + ' '
      mid = mid.replace(new RegExp(ch1, 'g'), ch2)
      ch1 = ',' + ancienNom + ','
      ch2 = ',' + nouveauNom + ','
      mid = mid.replace(new RegExp(ch1, 'g'), ch2)
      ch1 = ' ' + ancienNom + ','
      ch2 = ' ' + nouveauNom + ','
      mid = mid.replace(new RegExp(ch1, 'g'), ch2)
      ch1 = ' ' + ancienNom + ' '
      ch2 = ' ' + nouveauNom + ' '
      mid = mid.replace(new RegExp(ch1, 'g'), ch2)
      ch1 = ' ' + ancienNom + '}'
      ch2 = ' ' + nouveauNom + '}'
      mid = mid.replace(new RegExp(ch1, 'g'), ch2)
      ch1 = ',' + ancienNom + '}'
      ch2 = ',' + nouveauNom + '}'
      mid = mid.replace(new RegExp(ch1, 'g'), ch2)
      this.chaineCommentaire = left + mid + right
    }
    ind = ind + code.length - 1
  }
}
CLatex.prototype.chaineDesignation = function () {
  return 'desLatex'
}

// Fonction rajoutée version 6.7.2 pour que quand on lit une lsite d'objets la liste soit au courant
// si elle nécessite d'utiliser MathJax ou non
CLatex.prototype.read = function (inps, list) {
  this.listeProprietaire.useLatex = true
  CCommentaire.prototype.read.call(this, inps, list)
}