AGSScriptModuleKitaiCe module permet de transformer un bouton en zone de saisie à plusieurs lignesBloc-Notes1.0beta¼d// Si BLOC_CURSEUR > 0, cela représente le mode de curseur dont utiliser l'image lorsque la souris survole le bloc #define BLOC_CURSEUR 0 String sarray[]; int indexes[]; int nb_sarrays, nb_indexes; static function StringArray::InsertAt(int n, String texte) { if (n > nb_sarrays) n = nb_sarrays; if (n < 0) n = 0; String tmp[]; tmp = new String[nb_sarrays+1]; int i = 0; while (i < nb_sarrays) { if (i < n) tmp[i] = sarray[i]; else tmp[i+1] = sarray[i]; i++; } nb_sarrays++; sarray = new String[nb_sarrays]; i = 0; while (i < nb_sarrays) { if (i == n) sarray[i] = texte; else sarray[i] = tmp[i]; i++; } i = 0; while (i < nb_indexes) { if (indexes[i] > n) indexes[i]--; i++; } return n; } static String StringArray::PopAt(int n) { if (n > nb_sarrays) n = nb_sarrays; if (n < 0) n = 0; String retour = sarray[n]; nb_sarrays--; if (nb_sarrays == 0) return retour; String tmp[]; tmp = new String[nb_sarrays]; int i = 0; while (i < nb_sarrays) { if (i < n) tmp[i] = sarray[i]; else tmp[i] = sarray[i+1]; i++; } sarray = new String[nb_sarrays]; i = 0; while (i < nb_sarrays) { sarray[i] = tmp[i]; i++; } i = 0; while (i < nb_indexes) { if (indexes[i] > n) indexes[i]--; i++; } return retour; } function StringArray::Add(String ligne) { if (this.taille == 0) { this.index = nb_indexes; int tmp[]; tmp = new int[nb_indexes+1]; int i = 0; while (i < nb_indexes) { tmp[i] = indexes[i]; i++; } nb_indexes++; indexes = new int[nb_indexes]; i = 0; while (i < nb_indexes) { indexes[i] = tmp[i]; i++; } indexes[this.index] = nb_sarrays; } StringArray.InsertAt(indexes[this.index] + this.taille, ligne); this.taille++; return indexes[this.index] + this.taille; } String StringArray::Pop(int n) { if (this.taille < 1) return ""; if ((n < 0) || (n > this.taille-1)) n = this.taille-1; this.taille--; return StringArray.PopAt(indexes[this.index] + n); } String StringArray::geti_l(int index) { if (index < 0) index = 0; if (index > this.taille-1) index = this.taille-1; return sarray[indexes[this.index] + index]; } // BOUTON représente le bouton qui sert de bloc-notes Button* Bouton; // COULEUR représente la couleur du fond du bloc-notes int Couleur; // FOND_SELECT représente la couleur de fond lors d'une sélection int Fond_Select; // NUM_SPR représente le numéro de la sprite de fond du bouton, s'il y en a une int Num_Spr = -1; // BLOCTEXTE contient le texte du bloc String BlocTexte; // CADRE contiendra chaque ligne finale StringArray cadre; // BUFFER contient le texte copié/coupé String Buffer; // La sprite qui représente la zone de saisie DynamicSprite* bloc; // La surface buffer, qui n'a pas le curseur DrawingSurface* surf_buffer; // A sert à faire clignoter le curseur tous les X cycles int a = 0; // AFFCUR représente l'état (affiché ou non) du curseur bool affcur = false; // Le # de la lettre sur laquelle se trouve le curseur int curs = 0; // La position où l'on a cliqué avant de relâcher int sel = 0; // Le # de la ligne tout en haut de la surface int top_ligne = 0; // Les coordonnées du curseur (X en pixels, Y en # de ligne) int x_curs, y_curs; // Cette fonction retourne une copie d'une string avec le caractère LETTRE inséré à POS String InsertAt(this String*, int pos, char lettre) { String tmp = this; if (pos < 0) pos = 0; if (pos == tmp.Length) tmp = tmp.AppendChar(lettre); else { if (pos > tmp.Length) pos = tmp.Length; tmp = String.Format("%s%c%s", tmp.Substring(0, pos), lettre, tmp.Substring(pos, tmp.Length-pos)); } return tmp; } // Cette fonction retourne une copie d'une string avec le TEXTE inséré à POS String InsertStringAt(this String*, int pos, String texte) { String tmp = this; if (pos < 0) pos = 0; if (pos == tmp.Length) tmp = tmp.Append(texte); else { if (pos > tmp.Length) pos = tmp.Length; tmp = String.Format("%s%s%s", tmp.Substring(0, pos), texte, tmp.Substring(pos, tmp.Length-pos)); } return tmp; } function RemplitCadre(this DrawingSurface*, String texte, FontType police) { // On "rase" le cadre while (cadre.taille > 0) cadre.Pop(); // TMP contient la ligne à parser, TMP_MOTS contient la ligne à ajouter String tmp = "", tmp_mots = ""; // I représente le caractère de TEXTE en cours d'inspection int i = 0, font_height = GetTextHeight("I", police, GetTextWidth("I", police)); // On va parcourir chaque caractère de TEXTE un par un while (i < texte.Length) { // On ajoute le caractère en cours à TMP tmp = tmp.AppendChar(texte.Chars[i]); // Si TMP ne dépasse pas la largeur de la surface et que le caractère n'est pas un retour ligne... if ((GetTextWidth(tmp.Replace(String.Format("%c", 10),""), police) < this.Width) && (texte.Chars[i] != 10)) { // ... et si on se trouve à un espace, TMP_MOTS prend la valeur de TMP if (texte.Chars[i] == ' ') tmp_mots = tmp; } // Sinon (si TMP dépasse la largeur) else { // Si le caractère est un retour à la ligne, on ajoute le dernier mot à la ligne if (texte.Chars[i] == 10) tmp_mots = tmp; // Si TMP_MOTS est vide, c'est que le mot en cours à lui seul dépasse la longueur : on le coupe if (tmp_mots == "") tmp_mots = tmp.Truncate(tmp.Length-1); // On ajoute TMP_MOTS comme nouvelle ligne cadre.Add(tmp_mots); // Et on coupe TMP_MOTS du début de TMP tmp = tmp.Substring(tmp_mots.Length, tmp.Length - tmp_mots.Length); // Enfin on entame une nouvelle TMP_MOTS tmp_mots = ""; } i++; } // Une fois terminé on ajoute la dernière ligne au cadre cadre.Add(tmp); } function Ecrit(this DrawingSurface*, int curseur, FontType police) { String tmp; int font_height = GetTextHeight("I", police, GetTextWidth("I", police)); // Calcul du curseur int nb_car, li, li_curs, li_sel, nb_sel; // NB_CAR est le nombre de caractères scrutés, LI la ligne à laquelle on est rendu while (li < cadre.taille) { // Tant qu'on n'a pas dépassé la position du curseur tmp = cadre.geti_l(li); // On récupère la ligne LI if (nb_car <= curseur) { nb_car += tmp.Length; // On ajoute sa longueur à NB_CAR li_curs++; } if (nb_sel <= sel) { nb_sel += tmp.Length; li_sel++; } li++; // Et on passe à la ligne suivante } li = li_curs; // Une fois qu'on a dépassé la position du curseur, LI représente la ligne suivant celle où se trouve le curseur if (li > 0) y_curs = li-1; if (li_sel > 0) li_sel--; // On récupère la ligne où se trouve le curseur tmp = cadre.geti_l(y_curs); // On calcule la position du caractère-curseur dans la ligne en question int x_relatif = tmp.Length - (nb_car - curseur); // Si cette position est la première, ou si le curseur est tout simplement au tout début, 0 if ((x_relatif == 0) || (curseur == 0)) x_curs = 0; // Sinon... else { tmp = tmp.Substring(0, x_relatif); x_curs = GetTextWidth(tmp.Replace(String.Format("%c", 10),""), police); } // Calcul de la position sélectionnée tmp = cadre.geti_l(li_sel); x_relatif = tmp.Length - (nb_sel - sel); if ((x_relatif == 0) || (sel == 0)) x_relatif = 0; else { tmp = tmp.Substring(0, x_relatif); x_relatif = GetTextWidth(tmp.Replace(String.Format("%c", 10),""), police); } // On calcule à quel point le curseur se trouve plus bas que la capacité en hauteur int depasse = ((y_curs+1)*(font_height+1)) - bloc.Height; // S'il se trouve effectivement "trop" bas... if ((depasse) > 0) { // ... on remplace la ligne du haut en conséquence si nécessaire int haut_ligne = FloatToInt(IntToFloat(depasse)/IntToFloat((font_height+1)), eRoundUp); if (haut_ligne > top_ligne) top_ligne = haut_ligne; } // Si le curseur est "trop" haut, on remplace en conséquence if (y_curs < top_ligne) top_ligne = y_curs; // Enfin, on calcule de combien de pixels il faut faire "glisser" la surface vers le haut int decal_y = top_ligne * (font_height+1); // T correspond au nombre total de lignes int t = cadre.taille; // Si l'utilisateur a spécifié un fond if (Num_Spr > -1) { this.Clear(COLOR_TRANSPARENT); this.DrawImage(0, 0, Num_Spr); } // Sinon, on efface simplement la surface else this.Clear(Couleur); // Traçage de la sélection if (sel != curs) { if (Fond_Select == COLOR_TRANSPARENT) this.DrawingColor = 65535 - Bouton.TextColor; else this.DrawingColor = Fond_Select; if (y_curs == li_sel) { if (curs < li_sel) this.DrawRectangle(x_curs, y_curs*font_height, x_relatif, (li_sel+1)*font_height); else this.DrawRectangle(x_relatif, li_sel*font_height, x_curs, (y_curs+1)*font_height); } else { if (curs < sel) { tmp = cadre.geti_l(y_curs); this.DrawRectangle(x_curs, y_curs*font_height, GetTextWidth(tmp.Replace(String.Format("%c",10), ""), Bouton.Font), (y_curs+1)*font_height); int i = y_curs+1; while (i < li_sel) { tmp = cadre.geti_l(i); this.DrawRectangle(0, i*font_height, GetTextWidth(tmp.Replace(String.Format("%c",10), ""), Bouton.Font), (i+1)*font_height); i++; } this.DrawRectangle(0, li_sel*font_height, x_relatif, (li_sel+1)*font_height); } else { tmp = cadre.geti_l(li_sel); this.DrawRectangle(x_relatif, li_sel*font_height, GetTextWidth(tmp.Replace(String.Format("%c",10), ""), Bouton.Font), (li_sel+1)*font_height); int i = li_sel+1; while (i < y_curs) { tmp = cadre.geti_l(i); this.DrawRectangle(0, i*font_height, GetTextWidth(tmp.Replace(String.Format("%c",10), ""), Bouton.Font), (i+1)*font_height); i++; } this.DrawRectangle(0, y_curs*font_height, x_curs, (y_curs+1)*font_height); } } } // La ligne à écrire String ligne; // On va dessiner chaque ligne à (0, #ligne * hauteur_police) this.DrawingColor = Bouton.TextColor; while (cadre.taille > 0) { ligne = cadre.Pop(0); this.DrawString(0, 1 + (t - cadre.taille - 1) * font_height - decal_y, police, ligne.Replace(String.Format("%c", 10),"")); } // On sauvegarde une copie surf_buffer = this.CreateCopy(); // On release this.Release(); // On retourne return; } // Cette fonction retourne la position (aboslue) du curseur de façon à ce qu'il soit placé sur la ligne nuémro LI // et qu'il reste au plus près possible de son ancienne position horizontale function CaractereProx(int li) { if (li >= cadre.taille) li = cadre.taille-1; int c = 0; String ligne = cadre.geti_l(li), tmp = ligne.Substring(0, c); // Tant qu'on n'est pas arrivé à un décalage dépassant l'actuel et qu'on n'a pas atteint la fin de la ligne while ((GetTextWidth(tmp.Replace(String.Format("%c", 10),""), Bouton.Font) < x_curs) && (c < ligne.Length)) { c++; // On ajoute un caractère à TMP tmp = ligne.Substring(0, c); } // Si on est sur le dernier caractère de la non dernière ligne et qu'il s'agit d'un espace ou d'un retour à la ligne if ((c == ligne.Length) && (li < cadre.taille-1) && ((ligne.Chars[c-1] == ' ') || (ligne.Chars[c-1] == 10))) c--; // Si on est allé plus loin que le premier caractère... if (c > 0) { // On vérifie si le curseur n'est pas plus près horizontalement du caractère précédent String tmpmoinsun = ligne.Substring(0, c-1); if ((GetTextWidth(tmp.Replace(String.Format("%c", 10),""), Bouton.Font) - x_curs) > (x_curs - GetTextWidth(tmpmoinsun.Replace(String.Format("%c", 10),""), Bouton.Font))) c--; } // NEWPOS vaudra la position de ce caractère, plus tous les caractères des lignes précédentes int i = 0, newpos = c; while (i < li) { tmp = cadre.geti_l(i); newpos += tmp.Length; i++; } if (newpos > BlocTexte.Length) newpos = BlocTexte.Length; return newpos; } // Lorsqu'on appuie sur une touche function on_key_press(int keycode) { if ((Bouton == null) || (!Bouton.OwningGUI.Visible)) return; if (BlocTexte == null) BlocTexte = ""; // SELECT[0] sera le premier caractère sélectionné et SELECT[1] le dernier int select[2]; select[0] = (curs < sel) * curs + (sel < curs) * sel; select[1] = (curs > sel) * curs + (sel > curs) * sel; // Si du texte est sélectionné et qu'on appuie sur une touche "effective"... if (((26 < keycode) && (keycode < 359)) || (keycode == eKeyDelete) || (keycode == eKeyBackspace) || (keycode == eKeyReturn) || (keycode == eKeyCtrlX) || ((keycode == eKeyCtrlP) && (Buffer != null))) { if (select[0] != select[1]) { // Si CtrlX : dans buffer if (keycode == eKeyCtrlX) Buffer = BlocTexte.Substring(select[0], select[1]-select[0]); // Si Backspace : on augmente le curseur if (IsKeyPressed(eKeyBackspace)) select[0]++; // Si Del : on réduit sel if (IsKeyPressed(eKeyDelete)) select[1]--; // Si la sélection "dépasse" la fin, on se contente de ne récupérer que jusqu'à SELECT[0] if (select[1] >= BlocTexte.Length) BlocTexte = BlocTexte.Truncate(select[0]); else BlocTexte = String.Format("%s%s", BlocTexte.Substring(0, select[0]), BlocTexte.Substring(select[1], BlocTexte.Length-select[1])); curs = select[0]; } } // Appui sur une touche alphabétique if (('A' <= keycode) && (keycode <= 'Z')) { char lettre; // Si aucun shift n'est pressé et que le capslock n'est pas activé ou s'il l'est et qu'un shift est pressé >> minuscule if ((!(IsKeyPressed(403)) && !(IsKeyPressed(404)) && (!System.CapsLock)) || ((System.CapsLock) && (IsKeyPressed(403) || IsKeyPressed(404)))) lettre = keycode + 32; else lettre = keycode; BlocTexte = BlocTexte.InsertAt(curs, lettre); curs++; } // Appui sur un caractère à afficher if (((32 <= keycode) && (keycode <= 64)) || ((91 <= keycode) && (keycode <= 255))) { BlocTexte = BlocTexte.InsertAt(curs, keycode); curs++; } // Appui sur CtrlP if ((keycode == eKeyCtrlP) && (Buffer != null)) { BlocTexte = BlocTexte.InsertStringAt(curs, Buffer); curs += Buffer.Length; } // Appui sur Return if (keycode == eKeyReturn) { BlocTexte = BlocTexte.InsertAt(curs, 10); curs++; } // Appui sur Bakcspace if ((keycode == eKeyBackspace) && (curs > 0)) { BlocTexte = String.Format("%s%s", BlocTexte.Substring(0, curs-1), BlocTexte.Substring(curs, BlocTexte.Length-curs)); curs--; } // Appui sur Suppr if ((keycode == eKeyDelete) && (curs < BlocTexte.Length)) BlocTexte = String.Format("%s%s", BlocTexte.Truncate(curs), BlocTexte.Substring(curs+1, BlocTexte.Length-1)); // On remplit le cadre if (bloc == null) bloc = DynamicSprite.Create(Bouton.Width, Bouton.Height); DrawingSurface* surf = bloc.GetDrawingSurface(); surf.RemplitCadre(BlocTexte, Bouton.Font); // Appui sur Ctrl-A if (keycode == eKeyCtrlA) { sel = 0; curs = BlocTexte.Length; } // Appui sur Ctrl-C if ((keycode == eKeyCtrlC) && (select[0] != select[1])) Buffer = BlocTexte.Substring(select[0], select[1]-select[0]); // Appui sur gauche if ((keycode == eKeyLeftArrow) && (curs > 0)) { if (IsKeyPressed(405) || IsKeyPressed(406)) { int i; if (curs >= BlocTexte.Length) i = BlocTexte.Length-1; else i = curs-1; while ((i > 0) && (BlocTexte.Chars[i] > 48)) i--; curs = i+1; } curs--; } // Appui sur droite if ((keycode == eKeyRightArrow) && (curs < BlocTexte.Length)) { if (IsKeyPressed(405) || IsKeyPressed(406)) { int i = curs+1; while ((i < BlocTexte.Length) && (BlocTexte.Chars[i] > 48)) i++; curs = i-1; } curs++; } // Appui sur fin if (keycode == eKeyEnd) { if (IsKeyPressed(405) || (IsKeyPressed(406))) curs = BlocTexte.Length; else { x_curs = surf.Width + 10; curs = CaractereProx(y_curs); } } // Appui sur Home if (keycode == eKeyHome) { if (IsKeyPressed(405) || (IsKeyPressed(406))) curs = 0; else { x_curs = 0; curs = CaractereProx(y_curs); } } // Appui sur haut if ((keycode == eKeyUpArrow) && (y_curs > 0)) curs = CaractereProx(y_curs-1); // Appui sur bas if ((keycode == eKeyDownArrow) && (y_curs < cadre.taille-1)) curs = CaractereProx(y_curs+1); // Si on a appuyé sur une touche sans maintenir shift (sauf Ctrl-A et Ctrl-C), alors sel = curs if ((keycode != eKeyCtrlA) && (keycode != eKeyCtrlC) && (!((IsKeyPressed(403) || IsKeyPressed(404)) && (370 < keycode ) && (keycode < 382)))) sel = curs; // On affiche le cadre surf.Ecrit(curs, Bouton.Font); Bouton.NormalGraphic = bloc.Graphic; // On relance le clignotement du curseur a = 0; affcur = true; ClaimEvent(); } bool Clique = false; bool CliqueSurControl = false; function repeatedly_execute() { if ((Bouton == null) || (!Bouton.OwningGUI.Visible) || (bloc == null)) return; GUIControl* control = GUIControl.GetAtScreenXY(mouse.x, mouse.y); // Si l'utilisateur a spécifié un curseur particulier if (BLOC_CURSEUR > 0) { if (control == Bouton) mouse.UseModeGraphic(BLOC_CURSEUR); else mouse.UseDefaultGraphic(); } // Si besoin, on redimensionne le bloc à la bonne taille if ((bloc.Width != Bouton.Width) || (bloc.Height != Bouton.Height)) { bloc.Resize(Bouton.Width, Bouton.Height); DrawingSurface* surf = bloc.GetDrawingSurface(); surf.RemplitCadre(BlocTexte, Bouton.Font); surf.Ecrit(curs, Bouton.Font); Bouton.NormalGraphic = bloc.Graphic; } int font_height = GetTextHeight("I", Bouton.Font, GetTextWidth("I",Bouton.Font)), decal_y = top_ligne * (font_height+1); // Gestion du clignotement du curseur (tous les 20 cycles) if (!(a % 20)) { if (affcur) { DrawingSurface* surf = bloc.GetDrawingSurface(); surf.DrawSurface(surf_buffer); surf.DrawingColor = Bouton.TextColor; surf.DrawLine(x_curs, y_curs*font_height - decal_y, x_curs, (y_curs+1)*font_height - decal_y); surf.Release(); Bouton.NormalGraphic = bloc.Graphic; } else { DrawingSurface* surf = bloc.GetDrawingSurface(); surf.DrawSurface(surf_buffer); surf.Release(); Bouton.NormalGraphic = bloc.Graphic; } affcur = true - affcur; a = 1; // Retour à 1 } else a++; // Gestion du clic if (Mouse.IsButtonDown(eMouseLeft)) { if (!Clique) { Clique = true; // Si on clique effectivement sur le bouton if (control == Bouton) { CliqueSurControl = true; // On remplit le cadre DrawingSurface* surf = bloc.GetDrawingSurface(); surf.RemplitCadre(BlocTexte, Bouton.Font); // On calcule la position X relative de la souris et le # de ligne où elle se trouve x_curs = mouse.x - (Bouton.OwningGUI.X + Bouton.X); y_curs = (mouse.y - (Bouton.OwningGUI.Y + Bouton.Y) + decal_y) / font_height; // Puis on cherche le caractère le plus proche de cette position curs = CaractereProx(y_curs); sel = curs; // On affiche le cadre surf.Ecrit(curs, Bouton.Font); Bouton.NormalGraphic = bloc.Graphic; } else CliqueSurControl = false; } else if (CliqueSurControl) { // On remplit le cadre DrawingSurface* surf = bloc.GetDrawingSurface(); surf.RemplitCadre(BlocTexte, Bouton.Font); // On calcule la position X relative de la souris et le # de ligne où elle se trouve x_curs = mouse.x - (Bouton.OwningGUI.X + Bouton.X); y_curs = (mouse.y - (Bouton.OwningGUI.Y + Bouton.Y) + decal_y) / font_height; // Puis on cherche le caractère le plus proche de cette position curs = CaractereProx(y_curs); // On affiche le cadre surf.Ecrit(curs, Bouton.Font); Bouton.NormalGraphic = bloc.Graphic; } } else if (Clique) { Clique = false; CliqueSurControl = false; } } // Convertit un bouton en bloc-note function BlocN_Convert(this Button*, int couleur_fond, int fond_select) { Bouton = this; Couleur = couleur_fond; Fond_Select = fond_select; if (this.NormalGraphic > 0) Num_Spr = this.NormalGraphic; BlocTexte = Bouton.Text; Bouton.Text = ""; curs = BlocTexte.Length; sel = curs; bloc = DynamicSprite.Create(Bouton.Width, Bouton.Height); DrawingSurface* surf = bloc.GetDrawingSurface(); surf.Clear(couleur_fond); surf.RemplitCadre(BlocTexte, Bouton.Font); surf.Ecrit(curs, Bouton.Font); Bouton.NormalGraphic = bloc.Graphic; } // Retourne tout le texte contenu dans un bouton String BlocN_GetText(this Button*) { if (this == Bouton) return BlocTexte; } // Retourne le nombre de lignes que peut afficher le bloc-notes à la fois function BlocN_RowCount(this Button*) { if (this == Bouton) { int font_height = GetTextHeight("I", Bouton.Font, GetTextWidth("I", Bouton.Font)); return bloc.Height / (font_height+1); } } // Retourne le nombre de lignes contenues (affichées ou non) dans le bloc-notes function BlocN_LinesCount(this Button*) { if (this == Bouton) { surf_buffer.RemplitCadre(BlocTexte, Bouton.Font); return cadre.taille; } } // Retourne le numéro de la ligne affichée tout en haut du bloc-notes function BlocN_GetTopline(this Button*) { if (this == Bouton) return top_ligne; } // Retourne un tableau dynamique de 2 positions dont la première représente la ligne où se trouve le curseur, // et la seconde le caractère sur cette ligne où se trouve le curseur. // Exemple : // int curseur[] = btn.BlocN_GetCurseurPos(); // Display("Le curseur se trouve a la %deme lettre de la %deme ligne", curseur[1], curseur[0]); // int[] BlocN_GetCursorPos(this Button*) { if (this == Bouton) { int ret[] = new int[2]; ret[0] = y_curs; surf_buffer.RemplitCadre(BlocTexte, Bouton.Font); int i = 0, n; String tmp; while (i < y_curs) { tmp = cadre.geti_l(i); n += tmp.Length; i++; } ret[1] = curs - n; return ret; } } // Place le curseur sur le caractère numéro CARACTERE de la ligne numéro LIGNE function BlocN_SetCursorPos(this Button*, int ligne, int caractere) { if (this == Bouton) { if (ligne >= this.BlocN_LinesCount()) ligne = this.BlocN_LinesCount(); if (ligne < 0) ligne = 0; y_curs = ligne; DrawingSurface* surf = bloc.GetDrawingSurface(); surf.RemplitCadre(BlocTexte, Bouton.Font); int i = 0, n; String tmp; while (i < y_curs) { tmp = cadre.geti_l(i); n += tmp.Length; i++; } tmp = cadre.geti_l(i); if (caractere >= tmp.Length) caractere = tmp.Length-1; curs = n + caractere; surf.Ecrit(curs, Bouton.Font); Bouton.NormalGraphic = bloc.Graphic; } } // Place la ligne nuémro N en haut du bloc-notes (et place automatiquement le curseur sur celle-ci) function BlocN_SetTopline(this Button*, int n) { if (this == Bouton) { int tot = this.BlocN_LinesCount(); if (n >= tot) n = tot-1; if (n < 0) n = 0; top_ligne = n; y_curs = top_ligne; curs = CaractereProx(y_curs); sel = curs; DrawingSurface* surf = bloc.GetDrawingSurface(); surf.RemplitCadre(BlocTexte, Bouton.Font); surf.Ecrit(curs, Bouton.Font); Bouton.NormalGraphic = bloc.Graphic; } } // Remplace le texte du bloc-notes par TEXTE function BlocN_SetText(this Button*, String texte) { if (this != Bouton) return; BlocTexte = texte; DrawingSurface* surf = bloc.GetDrawingSurface(); surf.RemplitCadre(BlocTexte, Bouton.Font); surf.Ecrit(curs, Bouton.Font); Bouton.NormalGraphic = bloc.Graphic; } // Sauvegarde le texte du bloc-notes dans FICHIER // ATTENTION : le fichier FICHIER est écrasé par cette action function BlocN_SaveInFile(this Button*, String fichier) { File* tmp = File.Open(fichier, eFileWrite); tmp.WriteRawLine(BlocTexte); tmp.Close(); } // Charge le texte contenu dans FICHIER dans le bloc-notes function BlocN_LoadFile(this Button*, String fichier) { if (!File.Exists(fichier)) return; String txt = ""; File* tmp = File.Open(fichier, eFileRead); while (!tmp.EOF) { // On ne veut pas du caractère ASCII 13 (retour chariot) txt = txt.Replace(String.Format("%c%c", 13, 10), String.Format("%c",10)); txt = txt.Replace(String.Format("%c%c", 10, 13), String.Format("%c",10)); txt = txt.Replace(String.Format("%c", 13), String.Format("%c",10)); if (txt != "") txt = txt.AppendChar(10); txt = txt.Append(tmp.ReadRawLineBack()); } tmp.Close(); this.BlocN_SetText(txt); } Ðstruct StringArray { int index; int taille; import function Add(String ligne); import String Pop(int n = -1); import function Get(int n); import static function InsertAt(int n, String texte); // $AUTOCOMPLETEIGNORE$ import static String PopAt(int n); // $AUTOCOMPLETEIGNORE$ import static function InsertArray(); // $AUTOCOMPLETEIGNORE$ import attribute String l[]; import String geti_l(int index); // $AUTOCOMPLETEIGNORE$ }; import function BlocN_Convert(this Button*, int couleur_fond = COLOR_TRANSPARENT, int fond_select = COLOR_TRANSPARENT); import String BlocN_GetText(this Button*); import function BlocN_RowCount(this Button*); import function BlocN_LinesCount(this Button*); import function BlocN_GetTopline(this Button*); import int[] BlocN_GetCursorPos(this Button*); import function BlocN_SetCursorPos(this Button*, int ligne, int caractere); import function BlocN_SetTopline(this Button*, int n); import function BlocN_SetText(this Button*, String texte); // ATTENTION : le fichier FICHIER est écrasé par cette commande import function BlocN_SaveInFile(this Button*, String fichier); import function BlocN_LoadFile(this Button*, String fichier); AÞ£;ej÷´