Editeur de texte en C

en tous cas, le point C, c’est sensible. :laughing:

Voila le code source actuel :
Ma principale question concerne la persistance de l’interface graphique lors du lancement du programme. En effet, j’ai essaye differentes methodes pour que l’interface reste affichee au lancement du programme mais rien a faire. Pour le moment la solution retenue (mais je la trouve pas elegante, c’est de simuler l’appui sur la touche Espace avec la fonction ungetch(’ '); et de comparer le code ASCII retourne par la fonction getch() dans un boucle while. Le temps que la valeur lue est 32 (ASCII de Espace), on fait appel a la fonction d’affichage. Sinon on poursuit le programme. Voila sinon comme precedemment les remarques sont les bienvenues (autres que pre/post incrementation, ca j’ai pas encore change Yoko :p).
Amicalement
Doby

Fichier editor.c

[code]#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include “…/Include/editor.h”

int main(void){
editor Editor;
Editor.Position = 0;
Editor.Length = 0;

//Init terminal
initscr();
curs_set(0);
noecho();
keypad(stdscr,TRUE);
nodelay(stdscr, TRUE);
cbreak();

//Init buffer
InitBuffer(&Editor);

//Init graphic (peu convenable)
ungetch(’ ');
while(getch() == 32){
PrintBuffer(Editor);
usleep(5000);
}

//Main loop
while(1){
UseBuffer(&Editor);
usleep(5000);
}

//End of programm
endwin();
system(“clear”);
exit (0);
}

/*

  • All cells of the buffer contain the caracter ‘\0’
    */
    void InitBuffer(editor * Editor){
    int index = 0;
    for(index = 0; index < length; index++){
    Editor->buffer[index] = ‘\0’;
    }
    }

/*

  • Move cursor in the buffer + Insert & modify content of the buffer
    */
    void UseBuffer(editor * Editor){
    int key = 0;
    FILE * handle = NULL;

//Get ASCII code of the key
key = getch();

//Priority for escape sequence
if (key == ESCAPE)
Quit();

//Others ASCII code
switch(key)
{
case KEY_F(5):
handle = fopen(“untitled”,“w+”);
fwrite(Editor->buffer, sizeof(char), Editor->Length, handle);
fclose(handle);
break;

case KEY_F(6):
  handle = fopen("untitled", "r+");
  Editor->Length = fread(Editor->buffer, sizeof(char), length, handle);
  Editor->Position = 0;
  break;
  
case KEY_UP:
  if(Editor->Position > width)
Editor->Position -= width;
  break;
  
case KEY_DOWN:
  if(Editor->Position < length - width - 1)
Editor->Position += width;
  break;
  
case KEY_LEFT:
  if(Editor->Position > 0)
  Editor->Position--;
  break;
  
case KEY_RIGHT:
  if(Editor->Position < length - 1)
  Editor->Position++;
  break;
  
case KEY_BACKSPACE:
  if(Editor->Position > 0){
MoveData(Editor, 0);
Editor->Position--;
Editor->Length--;
  } 
  
  if(Editor->Position == 0){
MoveData(Editor, 0);
Editor->buffer[0] = '\0';
Editor->Length--;
  }
  break;
  
case KEY_HOME:
  Editor->Position -= (Editor->Position % width);
  break;
  
case ENTER:
  if(Editor->Position < length - width - 1){
Editor->Position = (Editor->Position + width - (Editor->Position % width));
Editor->Length = (Editor->Length + width - (Editor->Length % width));
  }
  break;
  
default:
  if(key >= 32 && key <= 126){
MoveData(Editor, 1);
Editor->buffer[Editor->Position] = (char)key;
Editor->Length++;
if(Editor->Position < length - 1)
  Editor->Position++;
  }
  
  else{
return;
  }
  
  break;
}

//Print modifications
PrintBuffer(*Editor);
}

/*

  • MoveData
  • Move existing data in the buffer (lose last caracter in the buffer)
    */
    void MoveData(editor * Editor, int way){
    int index = 0;

//Insert new data
if(way == 1){
for(index = length - 1; index > Editor->Position; index–){
Editor->buffer[index] = Editor->buffer[index - 1];
}
}

//Delete existing data (BACKSPACE)
if(way == 0){
for(index = Editor->Position - 1; index < length - 1; index++){
Editor->buffer[index] = Editor->buffer[index + 1];
}
Editor->buffer[length - 1] = ‘\0’;
}
}

/*

  • Print buffer
    */
    void PrintBuffer(editor Editor){
    int line = 0, column = 0, index = 0;
    PrintBorders();

//Print content of the buffer
for(index = 0; index <= Maximum(Editor.Length, Editor.Position); index++){
line = (index / width);
column = (index - line * width);
if(index == Editor.Position)
mvprintw(line + 4,column + 1, “_”);
else
mvprintw(line + 4, column + 1, “%c”, Editor.buffer[index]);
}
refresh();
}

/*

  • Print Borders
    */
    void PrintBorders(void){
    WINDOW * screen, *menu, *command;
    screen = newwin(length / width + 2, width + 2, 3, 0);
    menu = newwin(3, 82, 0, 0);
    command = newwin(3, 82, length / width + 5, 0);

//Print borders
box(screen, ACS_VLINE,ACS_HLINE);
wrefresh(screen);
box(menu, ACS_VLINE, ACS_HLINE);
box(command, ACS_VLINE, ACS_HLINE);

//Print menu
mvwprintw(menu, 1, 2, “Quit = ESC”);
mvwprintw(menu, 1, 14, “Save = F5”);
mvwprintw(menu, 1, 25, “Load = F6”);
wrefresh(menu);

//Print command
mvwprintw(command, 1, 2, “Load/Save file named : untitled”);
wrefresh(command);
}

/*

  • Quit Editor
    */
    void Quit(void){
    endwin();
    system(“clear”);
    exit (0);
    }

/*

  • Maximum return maximum value between two values
    */
    int Maximum(int value1, int value2){
    if(value1 >= value2)
    return value1;
    return value2;
    }
    [/code]

Fichier editor.h

/*
 * Simple text editor by Doby
 */

#ifndef EDITOR_H
#define EDITOR_H

/*
 * Define buffer size and line size (width)
 */
#define length 2400
#define width 80

/*
 * Define values of ASCII keys
 */
#define ENTER 10
#define ESCAPE 27

/*
 * Struture for the editor
 */
typedef struct _editor{
  char buffer[length];
  int Position;
  int Length;
} editor;

/*
 * InitBuffer(editor * Editor)
 * All cells of the buffer contain the caracter '\0'
 */
void InitBuffer(editor * Editor);

/*
 * UseBuffer(editor * Editor)
 * Move the cursor in the buffer + Insert & Modify content of the buffer
 */
void UseBuffer(editor * Editor);

/*
 * MoveData(editor * Editor, int way)
 * Move existing data in the buffer (lose last caracter in the buffer)
 */
void MoveData(editor * Editor, int way);

/*
 * PrintBuffer(editor Editor)  print the content of the buffer
 * PrintBorders(WINDOW * screen) print the borders of the interface
 */
void PrintBuffer(editor Editor);
void PrintBorders(void);

/*
 * Quit Editor
 */
void Quit(void);

/*
 * Maximum(int value1, int value2) return maximum value between two values
 */
int Maximum(int value1, int value2);

#endif //EDITOR_H
/*
 * All cells of the buffer contain the caracter '\0' 
 */
void InitBuffer(editor * Editor){
  int index = 0;
  for(index = 0; index < length; index++){
    Editor->buffer[index] = '\0';
  }
}

Cette fonction, ça se remplace aisément par:

void InitBuffer(editor *E)
{
  (void) memset(E->buffer, length, 0);
}
  switch(key)
    {
    case KEY_F(5):
      handle = fopen("untitled","w+");
      fwrite(Editor->buffer, sizeof(char), Editor->Length, handle);
      fclose(handle);
      break;

Ça c’est un segfault. Il faut impérativement tester le retour de: fopen, et fwrite.

    case KEY_F(6):
      handle = fopen("untitled", "r+");
      Editor->Length = fread(Editor->buffer, sizeof(char), length, handle);
      Editor->Position = 0;
      break;

Idem.


/*
 * MoveData
 * Move existing data in the buffer (lose last caracter in the buffer)
 */
void MoveData(editor * Editor, int way){
  int index = 0;
  
  //Insert new data
  if(way == 1){
    for(index = length - 1; index > Editor->Position; index--){
      Editor->buffer[index] = Editor->buffer[index - 1]; 
    }
  }

J’avoue ne pas comprendre ce que tu veux faire la :slightly_smiling: Je pense pas que ça soit la meilleure façon de faire :slightly_smiling:

  //Delete existing data (BACKSPACE)
  if(way == 0){
    for(index = Editor->Position - 1; index < length - 1; index++){
      Editor->buffer[index] = Editor->buffer[index + 1];
    }
    Editor->buffer[length - 1] = '\0';
  }
}

Idem, tu connais memove memcpy & co?

/*
 * Simple text editor by Doby
 */

#ifndef EDITOR_H
#define EDITOR_H

/*
 * Define buffer size and line size (width)
 */
#define length 2400
#define width 80

Par convention, on défini TOUJOURS les constante sous forme de chaines en majuscules…


/*
 * Define values of ASCII keys
 */
#define ENTER 10
#define ESCAPE 27

Moi j’aurais plutot faire genre KEY_ENTER KEY_ESCAPE…

Sinon, ça doit déja être défini par ncurses.h je pense…


/*
 * Struture for the editor
 */
typedef struct _editor{
  char buffer[length];
  int Position;
  int Length;
} editor;

Généralement, on fais plutot ceci:

typedef struct editor_st_s {
 ...
} editor_st_t;

De cette façon tu sais imédiatement ce qu’est un editor_st_t: type d’une struct editor :slightly_smiling: Mais bon la c’est les gouts et les couleurs…

Courage, a+

@ed :
Salut et merci pour tes remarques. Memove, memcopy ou memset nan je ne connaissais absolument pas et c’est vrai que ca serait nettement plus efficace (en fait dans la fonction MoveData, c’est juste un deplacement d’un indice donne position jusqu’a la fin du buffer dans un sens ou dans un autre suivant le parametre way pour inserer ou supprimer des donnees dans le buffer).
Sinon ouais pour les test de fread et fwrite j’ai pas fait les verifications d’usage, la c’est entierement de ma faute :stuck_out_tongue:
Pour les constantes ouais je sais toujours en Majuscules :slightly_smiling:
Et sinon KEY_ENTER et KEY_ESCAPE alors KEY_ENTER deja defini mais ne correspond pas a la touche ENTER centrale (de memoire a verifier) et sinon je me rappelle plus si KEY_ESCAPE est definie dans ncurses.
Quant au coup de la structure c’est pas bete du tout bien que ca fait assez indigeste a premiere vue.
Je vais regarder pour memcopy & co.

CR pour carriage return code hexa 0x0D
LF pour line feed code hexa 0x0A

Après vérification, il a raison le bougre ;o