/*
* 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 { alignCenter, alignLeft, alignRight, traiteAccents } from 'src/kernel/kernel'
import NatObj from '../types/NatObj'
import NatCal from '../types/NatCal'
import Pointeur from '../types/Pointeur'
import Nat from '../types/Nat'
import CAffLiePt from './CAffLiePt'
import CListeObjets from './CListeObjets'
import { cens } from '../kernel/dom'
import Fonte from '../types/Fonte'
import StyleEncadrement from '../types/StyleEncadrement'
export default CCommentaire
/**
* Classe représentant un affichage de texte sur la figure.
* Si le texte est encadré de $ ce sera un affichage LaTeX.
* @constructor
* @extends CAffLiePt
* @param {CListeObjets} listeProprietaire La liste propriétaire.
* @param {CImplementationProto} impProto null ou la construction propriétaire.
* @param {boolean} estElementFinal true si l'objet est un élément final de construction.
* @param {Color} couleur La couleur d'éciture de l'éditeur (et du cadre éventuel).
* @param {number} xNom L'abscisse d'affichage de l'éditeur
* @param {number} yNom L'ordonnée d'affichage de l'éditeur
* @param {number} decX Décalage horizontal du nom
* @param {number} decY Décalage vertical du nom
* @param {boolean} masque true si l'éditeur est masqué
* @param {CPt} pointLie null ou pointe sur un point auquel l'affichage est lié.
* @param {number} taillePolice Taille de police à utiliser
* @param {number} encadrement entier pour le style d'encadrement (0, 1 ou 2, voir CAffLiePt).
* @param {boolean} effacementFond Passer true pour rendre le fond transparent
* @param {Color} couleurFond La couleur de fond
* @param {number} alignementHorizontal 0 pour alignement gauche, 1 pour centré, 2 pour droite.
* @param {number} alignementVertical 0 pour alignement vers le haut, 1 pour centré, 2 pour bas.
* @param {string} chaineCommentaire Le texte à afficher. S'il est entouré de $ ce sera un affichage LaTeX.
* @param {number} align alignement des lignes du texte, 0 pour alignement gauche, 1 pour centre et 2 pour droit
* @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
* @param {boolean} forceRightToLeft Si true, force l'écriture de droite à gauche
* (utilisé pour les tips et indications en arabe)
* @returns {CCommentaire}
*/
function CCommentaire (listeProprietaire, impProto, estElementFinal, couleur,
xNom, yNom, decX, decY, masque, pointLie, taillePolice, encadrement, effacementFond,
couleurFond, alignementHorizontal, alignementVertical, chaineCommentaire, align = alignLeft,
angText, fixed, forceRightToLeft = false) {
if (arguments.length !== 0) {
if (arguments.length === 1) CAffLiePt.call(this, listeProprietaire)
else {
CAffLiePt.call(this, listeProprietaire, impProto, estElementFinal, couleur, xNom, yNom,
decX, decY, masque, pointLie, taillePolice, encadrement, effacementFond, couleurFond, alignementHorizontal,
alignementVertical, angText, fixed)
this.chaineCommentaire = chaineCommentaire
this.align = align
this.forceRightToLeft = forceRightToLeft
}
this.listValDynUsed = new CListeObjets(listeProprietaire.uniteAngle, listeProprietaire.pointeurLongueurUnite)
}
}
CCommentaire.prototype = new CAffLiePt()
CCommentaire.prototype.constructor = CCommentaire
CCommentaire.prototype.superClass = 'CAffLiePt'
CCommentaire.prototype.className = 'CCommentaire'
CCommentaire.prototype.numeroVersion = function () {
// Version 9.5.0 : on passe à 3 car on ajoute aux affichages de texte un mode d'affichage : gauche, centre ou droit
return 3
}
// 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
CCommentaire.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 CCommentaire(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,
this.align, 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 utilsié pour les exportations tikz
ptelb.id = this.id
return ptelb
}
CCommentaire.prototype.getNature = function () {
return NatObj.NCommentaire
}
CCommentaire.prototype.metAJour = function () {
this.determineDependances()
}
CCommentaire.prototype.donneChaine = function (chaine) {
this.chaineCommentaire = chaine
}
/**
* Fonction plaçant l'affichage de texte aux coordonnées (x,y)
* @param {number} x
* @param {number} y
* @returns {void}
*/
CCommentaire.prototype.placeEn = function (x, y) {
this.xNom = x
this.yNom = y
}
CCommentaire.prototype.rendChaineAffichage = function () {
return this.chaineAffichage
}
CCommentaire.prototype.ajouteAntecedents = function (liste) {
if (this.pointLie !== null) liste.add(this.pointLie)
}
/**
* Fonction renvoyant -1 si this.chaineCommentaire ne contient pas de soous-chaîne
* #Val ou \For et sinon renvoie l'indice du premier des deux rencontrés, formule.getValue()
* renvoyant true si c'est un #For qui a été trouvé et false sinon.
* @param{number} indDeb L'indice du début de la recherche
* @param{Pointeur} formule
**/
CCommentaire.prototype.indicePremierValOuForm = function (indDeb, formule) {
const indVal = this.chaineCommentaire.indexOf('#Val(', indDeb)
const indFor = this.chaineCommentaire.indexOf('#For(', indDeb)
if ((indVal === -1) && (indFor === -1)) return -1
if (((indVal > indFor) || (indVal === -1)) && (indFor !== -1)) {
formule.setValue(true)
return indFor
} else {
formule.setValue(false)
return indVal
}
}
/**
* Fonction faisant en sorte que this.listValDynUsed contienne
* la liste de tous les objets dont dépend le coomentaire par des appels
* à #Val() ou #For()
* @param {number} 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
* @returns {void}
*/
CCommentaire.prototype.determineDependances = function (indiceReel = -1) {
let jdeb, j, indparf, indsaut, ch, nomvaleur, indicecommentaire, pValeur
const bformule = new Pointeur(true)
this.listValDynUsed.retireTout()
// On examine la chaine à la recherche de #Val(
const len = this.chaineCommentaire.length
j = 0
if ((this.chaineCommentaire.indexOf('#Val(', j) === -1) && (this.chaineCommentaire.indexOf('#For(', j) === -1)) return
while (((jdeb = this.indicePremierValOuForm(j, bformule)) !== -1) && j < len) {
// On recherche la parenthèse fermante correspondante
indparf = this.chaineCommentaire.indexOf(')', jdeb + 5)
if (indparf === -1) j = len + 1
else {
indsaut = this.chaineCommentaire.indexOf('\n', jdeb + 5)
if ((indsaut !== -1) && (indsaut < indparf))j = indsaut + 1
else {
// On crée une chaine formé de ce qu'il y a entre #Val( et la parenthèse fermante
ch = this.chaineCommentaire.substring(jdeb + 5, indparf)
// On retire les éventuels espaces de cete chaine
ch = ch.trim()
// On sépare cette chaine avec les virgules
const 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
if (indiceReel !== -1) indicecommentaire = indiceReel
else indicecommentaire = this.listeProprietaire.indexOf(this)
// 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
if (indicecommentaire === -1) indicecommentaire = this.listeProprietaire.longueur() - 1
pValeur = this.pointeur(NatCal.NTteValPourComDyn, nomvaleur, indicecommentaire)
if (pValeur === null) j = indparf + 1
else {
/** Corrigé version mtgApp
natc = pValeur.getNatureCalcul();
if ((bformule.getValue() && (Nat.and(natc, NatCal.NCalcRouC |
NatCal.NTteFoncRouC))) || !bformule.getValue())
*/
if ((bformule.getValue() && pValeur.estDeNatureCalcul(Nat.or(NatCal.NCalcRouC,
NatCal.NTteFoncRouC))) || !bformule.getValue()) { this.listValDynUsed.add(pValeur) }
// Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
j = indparf + 1
}
}
}
}
}
}
CCommentaire.prototype.positionne = function (infoRandom, dimf) {
let jdeb, j, indparf, indsaut, ch, st, nomvaleur, indfin, pValeur, natc, chnombre, chnbdec, nbdecimales, chplus
const bformule = new Pointeur(true)
// On examine la chaine à la recherche de #Val(
const len = this.chaineCommentaire.length
let bufferAffichage = ''
j = 0
if ((this.chaineCommentaire.indexOf('#Val(', j) === -1) && (this.chaineCommentaire.indexOf('#For(', j) === -1)) {
this.chaineAffichage = this.chaineCommentaire
CAffLiePt.prototype.positionne.call(this, infoRandom, dimf)
return
}
while (((jdeb = this.indicePremierValOuForm(j, bformule)) !== -1) && j < len) {
bufferAffichage += this.chaineCommentaire.substring(j, jdeb)
// On recherche la parenthèse fermante correspondante
indparf = this.chaineCommentaire.indexOf(')', jdeb + 5)
if (indparf === -1) {
bufferAffichage += this.chaineCommentaire.substring(jdeb, len)
j = len + 1
} else {
// On recherche aussi un éventuel retour à la ligne
indsaut = this.chaineCommentaire.indexOf('\n', jdeb + 5)
if ((indsaut !== -1) && (indsaut < indparf)) {
bufferAffichage += this.chaineCommentaire.substring(jdeb, indsaut + 2)
j = indsaut + 1
} else {
// On crée une chaine formé de ce qu'il y a entre #Val( et la parenthèse fermante
ch = this.chaineCommentaire.substring(jdeb + 5, indparf)
// On retire les éventuels espaces de cete chaine
ch = ch.trim()
// On sépare cette chaine avec les virgules
st = ch.split(/\s*,\s*/)
if (st.length === 0) { // Pas de virgule
bufferAffichage += this.chaineCommentaire.substring(jdeb, indparf + 1)
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
// Si c'est le nom d'une valeur utilisée, elle est comprise dans la
// liste listValDynUsed
indfin = this.listValDynUsed.longueur() - 1
pValeur = this.listValDynUsed.pointeurParNatureCalcul(NatCal.NTteValPourComDyn,
nomvaleur, indfin)
if (pValeur === null) {
bufferAffichage += this.chaineCommentaire.substring(jdeb, indparf + 1)
j = indparf + 1
} else {
// Si la valeur n'existe pas, on ne l'inclut pas dans la chaîne à afficher
if (pValeur.existe) {
if (bformule.getValue()) {
// L'affichage de formule n'a de sens que pour un calcul ou une fonction
natc = pValeur.getNatureCalcul()
if (Nat.and(natc, NatCal.NCalcRouC | NatCal.NTteFoncRouC)) { bufferAffichage += pValeur.chaineCalcul }
} else {
chnombre = ''
if (st.length >= 2) {
chnbdec = st[1]
if (chnbdec === '+') {
chnombre = pValeur.rendChaineValeurPourCommentaire(2)
if (chnombre.indexOf('-') !== '0') chnombre = '+ ' + chnombre
} else {
// nbdec = parseInt(chnbdec);
nbdecimales = parseInt(chnbdec)
chnombre = pValeur.rendChaineValeurPourCommentaire(nbdecimales)
if (st.length >= 3) {
chplus = st[2]
if (chplus === '+') if (chnombre.indexOf('-') !== 0) chnombre = '+ ' + chnombre
}
}
} else {
// Si le nombre de décimales n'est pas précisé, on en met deux par défaut
chnombre = pValeur.rendChaineValeurPourCommentaire(2)
}
bufferAffichage += chnombre
}
}
j = indparf + 1
}
}
}
}
}
if (j < len) bufferAffichage += this.chaineCommentaire.substring(j, len)
this.chaineAffichage = bufferAffichage
CAffLiePt.prototype.positionne.call(this, infoRandom, dimf)
}
CCommentaire.prototype.depDe = function (p) {
if (this.elementTestePourDependDe === p) return this.dependDeElementTeste
return this.memDep(CAffLiePt.prototype.depDe.call(this, p) ||
this.listValDynUsed.depDe(p))
}
CCommentaire.prototype.dependDePourBoucle = function (p) {
return CAffLiePt.prototype.dependDePourBoucle.call(this, p) ||
this.listValDynUsed.dependDePourBoucle(p)
}
/**
* Fonction renvoyant un pointeur sur l'élément de type calcul de nature nat
* et ayant pour nom nom si le commentaire utilise ce calcul pour un affichage
* dynamique de valeur. Renvoie null s'il ne l'utilise pas.
* @param {Nat} nat
* @param {string} nom
* @param {number} indiceMaxi Indice dans la liste de début de la recherchee (vers le début de la liste)
* @returns {CValDyn}
*/
CCommentaire.prototype.pointeur = function (nat, nom, indiceMaxi) {
const list = this.listeProprietaire
// Modifié version 4.5 : Aussi à faire pour les objets intermédiaires car un CLatex ou un CCommentaire peut générer un lieu d'objets.
// Si le CLatex est un objet final de construction on recherhe d'abord la valeur
// dans les objets intermédiaires ou finaux de cette construction
// Important : on ne peut pas utiliser impProto car lors de getClone appelé par CImplementationProto.implemente
// le membre impProto n'a pas encore été établi
// Version 7.9.3 : On peut maintenant utiliser this.impProto car dans CImplementationProto.prototype.implemente
// on appelle getClone sur elb = proto.get(i) avec un troisième paramètre qui est pris en compte
// dans CCommentaire.prototype.getClone et CLatex.prototype.getClone
let i = indiceMaxi
if (this.estElementFinal || this.estElementIntermediaire()) {
const impProto = this.impProto
// Si on ne tombe pas sur un return on va forcément tomber sur le break et la recherche continuera
// au-dessous sur les éléments qui ne sont pas des objets intermédiaires de construction
while (i >= 0) {
const elb = list.get(i)
if (elb === impProto) {
i--
// Si on n'a paps trouvé on s'arrête à l'implémentation de prototype
break // On poursuivra la recherche dans le while suivant à partir de la valeur actuelle de i
}
if (elb.estElementFinal || elb.estElementIntermediaire()) {
if (elb.estDeNatureCalcul(nat)) {
if (elb.getNom() === nom) return elb
else i--
} else i--
} else i--
}
}
// Sinon on recherche dans tous les objets qui ne sont pas des objets intermédiaires de construction
// Version 8.7.3 : on continue la recherche vers l'arrière au lieu de vers l'avant dans la liste
// car il y a plus de chances que les calculs dynamiques utilisés par l'affichage de texte ou de LaTeX
// soient plus proche de l'affichage que du début de la figure
// Cette recherche est nécessaire même si this est un objet final de construction car elle sert
// lors de l'implémentation d'u prototype
while (i >= 0) {
const elb = list.get(i)
if (elb.estDeNatureCalcul(nat) && !elb.estElementIntermediaire()) {
if (elb.getNom() === nom) return elb
else i--
} else i--
}
return null
}
CCommentaire.prototype.chaineDesignation = function () {
return 'desCommentaire'
}
// Version 9.5 : les affichages de texte ont mantenant un attribut textAlign qui doit
// être géré différemment dans createg
CCommentaire.prototype.createg = function () {
let t, ch, h, anchor, y, ligaf, ch2, v
const len = this.chaineAAfficher.length
// Ajout version mtgApp
if (len === 0) return cens('g')
if (this.isLatex) return this.cLatexCreateg()
this.chaineAffichee = this.chaineAAfficher
// haut = Fonte.taille(this.taillePolice); Modifié version 5.0
const haut = this.taillePolice
const g = cens('g')
// L'élément va être d'abord caché. S'il est encadré ou efface le fond on rajoutera un élément en tête
// On commence à créer l'affichage en tenant commpte de l'alignement horizontal du texte
// dans le cas de plusieurs lignes puis on corrigera la position en tenant compte de l'alignement
// par rapport au point d'ancrage
switch (this.align) {
case alignRight :
anchor = 'End'
break
case alignCenter :
anchor = 'middle'
break
default :
anchor = 'start'
}
// On compte le nombre de lignes
let nblig = 1
let ind = -1
while ((ind = this.chaineAAfficher.indexOf('\n', ind + 1)) !== -1) nblig++
h = (nblig === 1) ? haut : haut + (nblig - 1) * (haut + 2)
// y = this.decY; // Corrigé version 6.0.1
y = 0
if (this.chaineAAfficher.search(/#H|#L/) !== -1) {
v = haut / 3
h += v
y += v
}
switch (this.alignementVertical) {
case CAffLiePt.alignVerCent :
y -= h / 2 + 1
break
case CAffLiePt.alignVerLow :
y -= h + 2
}
// Modifié version 4.9.2.3
// ligaf = y + haut - 1;
ligaf = y + haut - 2
// this.rectAff.height = h;
// Modifié version 4.9.9.4
// style = "text-anchor:" + anchor + ";font-size:" + haut +"px;" + "fill:" + this.couleur.rgb()+";";
// Modifié version 5.1.4 : IL faut préciser une fonte pour les textes
// Version 8.0 : on ne spécifie plus une police ainsi cela sera celle du div contenant la figure
// qui a un font-family à Roboto ce qui donnera un affichage identique aux affichages LaTX
// const sty = "font-family:'Times New Roman',Times,serif;text-anchor:" + anchor + ';fill:' + this.color + ';'
const sty = 'text-anchor:' + anchor + ';fill:' + this.color + ';'
const style = sty + 'font-size:' + haut + 'px;'
// Ajout version 5.0
const styleexp = sty + ';font-size:' + String(Math.round(haut * 2 / 3)) + 'px;'
// Modification version 5.0 : Une variable globale mémorisant le style d'écriture : italique, gras, souligne ou une combinaison de ces styles
const st = new Pointeur(Fonte.Normal)
if (this.chaineAAfficher.indexOf('\n') === -1) {
t = this.createLine(this.chaineAAfficher, haut, style, styleexp, ligaf, st)
g.appendChild(t)
} else {
ch = this.chaineAAfficher
// h = haut;
while ((ind = ch.indexOf('\n')) !== -1) {
ch2 = ch.substring(0, ind)
t = this.createLine(ch2, haut, style, styleexp, ligaf, st)
g.appendChild(t)
// Modification version 5.0 pour traiter exposants et indices
ligaf += haut + ((ch2.search(/#H|#L/) !== -1) ? haut / 3 + 2 : 2)
ch = ch.substring(ind + 1)
}
t = this.createLine(ch, haut, style, styleexp, ligaf, st)
g.appendChild(t)
}
g.setAttribute('visibility', 'hidden')
const svgAux = document.getElementById('mtgSvgAux')
svgAux.appendChild(g)
const box = g.getBBox()
const boxWidth = box.width
this.rectAff.y = y
// On crée un tableau qui va permettre de corriger l'alignement par rapport au point d'ancrage
// Chaque ligne correspond à un alignement (this.align) et ses termes correspondent à l'ancrage
// horizontal (this.horizontalAlign)
const tabAc = [
[0, -boxWidth / 2, -boxWidth], // Alignement des lignes à gauche
[boxWidth / 2, 0, -boxWidth / 2], // Alignement des lignes centré
[boxWidth, boxWidth / 2, 0]] // Alignement des lignes à droite
// Pour les affichages de texte (CCommentaire), depuis la version 9.5, on a un style d'alignement
// des lignes. Le style d'alignement par défaut est l'alignement à gauche
// const boxWidth = box.width
// Si la figure est en arabe il faut décaler les affichages pour obtenir un alignement à droite
// Pour ça on décale chaque ligne de l'affichage de texte
this.rectAff.x = box.x + tabAc[this.align][this.alignementHorizontal] + (this.forceRightToLeft ? boxWidth : 0)
for (const line of g.querySelectorAll('text')) {
// const widthLine = line.getBBox().width
// const align = this.align
line.setAttribute('dx', tabAc[this.align][this.alignementHorizontal] + (this.forceRightToLeft ? boxWidth : 0))
}
/*
////////////////////////////////////////////////////////////////////////////
// Ajout version 6.0 : Quand l'affichage doit être translaté et n'a pas à //
// être réaffiché; il faut connaître la position relative entre le //
// rectangle d'affichage et (xNom, y_no);
*/
// this.posRel = {x: this.rectAff.x - this.xNom, y : this.rectAff.y - this.yNom};
/// /////////////////////////////////////////////////////////////////////////
if (this.effacementFond || (this.encadrement !== StyleEncadrement.Sans)) {
this.rectAff.width = box.width + 4
this.rectAff.height = h + 6
this.creeRectangle(g)
} else {
this.rectAff.width = box.width
this.rectAff.height = h
}
svgAux.removeChild(g)
g.setAttribute('visibility', 'visible')
// Ligne suivante modifiée version 6.5.2
g.setAttribute('pointer-events', this.pointerevents)
// Ajout version Version 6.0
this.positionneAngText(g)
/// //////////////////////////////////////////////////////////////////////
return g
} // createg
CCommentaire.prototype.read = function (inps, list) {
CAffLiePt.prototype.read.call(this, inps, list)
this.chaineCommentaire = traiteAccents(inps.readUTF())
// Ajout version 5.0 pour traiter les $$ et ## représentés par un seul caractère
this.chaineCommentaire = this.chaineCommentaire.replace(/\$\$/g, '$')
// this.chaineCommentaire = this.chaineCommentaire.replace(/##/g,"#");
// Depuis la version 9.5 on a un alignement des lignes : gauche, centré ou droit
// Avant il était toujours aligné à gauche
if (this.nVersion === 3) this.align = inps.readInt()
else this.align = this.alignementHorizontal
this.listValDynUsed = new CListeObjets(list.uniteAngle, list.pointeurLongueurUnite)
if (this.listeProprietaire.className !== 'CPrototype') this.determineDependances()
// Ajout version 6.7.2 pour que le player mtg32 sache si la liste chargée nécessite MathJax ou non
const ch = this.chaineCommentaire
if (this.className === 'CCommentaire' && ch.charAt(0) === '$' && ch.charAt(ch.length - 1) === '$') {
this.listeProprietaire.useLatex = true
}
}
CCommentaire.prototype.write = function (oups, list) {
CAffLiePt.prototype.write.call(this, oups, list)
oups.writeUTF(this.chaineCommentaire)
// Depuis la version 9.5 on a un alignement des lignes : gauche, centré ou droit
oups.writeInt(this.align)
}
/**
* Fonction remmplaçant les appels dynamiques de la valeur nommée ancienNom par nouveauNom
* @param {string} ancienNom
* @param {string} nouveauNom
* @returns {boolean}
*/
CCommentaire.prototype.remplaceNomValeurDynamique = function (ancienNom, nouveauNom) {
// On supprime d'abord tous les caractères espace suivant une ( ou une virgule ou précédant une parenthèse
let buffer = this.chaineCommentaire
/* Inutile avec des expressions régulières
while((ind = buffer.indexOf("#Val( ")) !== - 1) {
buffer.deleteCharAt(ind+5);
}
while((ind = buffer.indexOf("#For( ")) !== - 1) {
buffer.deleteCharAt(ind+8);
}
*/
let ch1 = '#Val\\([ ]*' + ancienNom + '[ ]*\\)'
let ch2 = '#Val(' + 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)
ch1 = '#For\\([ ]*' + ancienNom + '[ ]*\\,'
ch2 = '#For(' + nouveauNom + ','
buffer = buffer.replace(new RegExp(ch1, 'g'), ch2)
const modif = (buffer !== this.chaineCommentaire)
this.chaineCommentaire = buffer
return modif
}