Voici un aperçu du résultat.
Télécharger la source : test2.fla (MX 2004)

Je remets la fonction décrite par derRaab a laquelle je n'ai pratiquement pas touché.

// getTextPosition : 
// calcule les coordonnées d'une expression dans une chaine
// en fonction du format de texte, et de la largeur du champ
function getTextPosition (text_fmt:TextFormat, complete_str:String, search_str:String, text_width:Number){
	var metrics;
 
	// largeur / hauteur de la  chaine recherchée :
	metrics = text_fmt.getTextExtent(search_str, text_width);
	var width = metrics.width;
	var height = metrics.height;
 
	// calculs :
	metrics = text_fmt.getTextExtent(complete_str.split(search_str)[0]+search_str, text_width);
	var bottom = metrics.height + 2;
	var totalHeight = metrics.height;
	var top = bottom - height;
 
	// Découpage du texte :
	var preSearch:Array = complete_str.split(search_str)[0].split(' ');
	var lastLine:Array = new Array();
	var cutting = true;
	while (cutting) {
		if (text_fmt.getTextExtent(preSearch.join(' '), text_width).height != totalHeight){
			cutting = false;
		} else {
			lastLine.push(preSearch.pop());
		}
	}
	lastLine.reverse();
 
	// début / fin :
	var left = text_fmt.getTextExtent(lastLine.join(' '),text_width).width + 2;
	var right = left + width;
	
	return {left:left, right:right, top:top, bottom:bottom}
}

Et le code pour tester : (notez que la police attribuée aux champs de texte créés est une police importée dans la librairie. Ca ne fonctionne pas autrement)

htmlContent = "Chaque enfant aura <gap identifier='G1'/> bonbons.\nIl restera <gap identifier='G1'/> bonbons dans la boîte.";
GapType = "input";
NbGaps = 2;
textwidth = 350;
maxWord = "100"; // mot le plus long
// TextFormat
var tf = new TextFormat();
tf.font = 'maFont';
tf.bold = true;
tf.size = 16;
 
// transformation balises <gap identifier="G1" /> en [motlepluslongX]
for (i=0; i<NbGaps; i++) {
	debutGap = htmlContent.indexOf ("<gap");
	finGap = htmlContent.indexOf ("/>") + 2;
	//htmlContent = htmlContent.substr (0, debutGap) + "[ " + (i+1) + " ]" + htmlContent.substr (finGap, htmlContent.length);
	htmlContent = htmlContent.substr (0, debutGap) + "[" + maxWord + (i+1) + "]" + htmlContent.substr (finGap, htmlContent.length);
}
 
// TextField
this.createTextField("textContent",1 , 0, 0, textwidth, 100);
textContent.embedFonts = true;
textContent.selectable = false;
textContent.html = true;
textContent.wordWrap = true;
textContent.autoSize = 'left';
textContent.htmlText = htmlContent;
textContent.setTextFormat(tf);
 
for (i=1; i<=NbGaps; i++) {
	// Récupérer les positions :
	//search_str = "[ " + i + " ]";
	search_str = "[" + maxWord + i + "]";
	var coords = getTextPosition(tf, textContent.text, search_str, textwidth);
 
	// creation du gap :
	this.createEmptyMovieClip("gap_mc" + i, 10+i);
	gapWidth = coords['right'] - coords['left'];
	gapHeight = coords['bottom'] - coords['top'];
	gapX = coords['left'];
	gapY = coords['top'];
	
	// dessin du cadre :
	with (this["gap_mc" + i]){
		_x = gapX;
		_y = gapY;
		beginFill(0xFFFFFF);
		lineStyle(2, 0x990000, 100, true, "none", "round", "miter", 1);
		lineTo(gapWidth, 0);
		lineTo(gapWidth, gapHeight);
		lineTo(0, gapHeight);
		lineTo(0,0);
	}
	// si les gap sont des champs de saisie :
	if (GapType == "input") {
		this["gap_mc" + i].createTextField ("saisie", 10, 2, -2, gapWidth, gapHeight + 10);
		this["gap_mc" + i].saisie.type = "input";
		this["gap_mc" + i].saisie.maxChars = maxWord.length;
		this["gap_mc" + i].saisie.text = ">";
		// embedFonts ne marche pas pour les champs de saisie (?)
		tf.font = "Arial";
		tf.color = 0x990000;
		this["gap_mc" + i].saisie.setTextFormat(tf);
		
		// comportement champs de saisie :
		this["gap_mc" + i].saisie.onSetFocus = function () {
			if (this.text == ">") {
				this.text = "";
			}
		}
		this["gap_mc" + i].saisie.onKillFocus = function () {
			if (this.text == "") {
				this.text = ">";
				this.setTextFormat(this._parent._parent.tf);
			}
		}
		this["gap_mc" + i].saisie.onChanged = function () {
			this.setTextFormat(this._parent._parent.tf);
		}
	}
}