Skip to content

Instantly share code, notes, and snippets.

@maeste
Created August 27, 2020 15:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maeste/dcd38871e8da761dfe2a627c97b44aa5 to your computer and use it in GitHub Desktop.
Save maeste/dcd38871e8da761dfe2a627c97b44aa5 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#define CHANGE_COMMAND 0
#define DELETE_COMMAND 1
/*
this struct stores all the contents of a line from its birth
the first element of the list is the first text written in the line,
then we have all the changes, element by element
we will use this structure to enable undo and redo
when we delete text of a line, we will create a new element in the list, with an empty text
*/
typedef struct line {
char text[1024];
struct line * next;
} line_t;
/*
maybe a list for the editor is not the best choice
the need is to access the line in a short time, so the best choice would be an array,
but we don't know how many lines can editor have
maybe a tree or an hash are the ones
typedef struct editor {
int line_number;
struct line * line;
struct editor * next;
struct editor * prev;
} editor_t;
*/
line_t* first_line = NULL;
/*
this structure is stack storing the commands. a command type
*/
typedef struct command_stack {
int command_type;
int line_number;
char previous_text[1024];
int group_lenght;
struct command_stack * next;
}command_stack_t;
command_stack_t * undo_stack = NULL;
command_stack_t * redo_stack = NULL;
// Append the new element to the start of the stack
void push(int command_type, int line_numeber, char previous_text[1024], int group_length, struct command_stack** stack){
struct command_stack* Element = (struct command_stack*)malloc(sizeof(struct command_stack));
Element -> command_type = command_type;
Element -> line_number = line_numeber;
Element -> group_lenght = group_length;
strcpy(Element -> previous_text, previous_text);
Element -> next = *stack;
(*stack) = Element;
}
// Remove element from the top of the stack
void pop(struct command_stack** stack){
if(*stack != NULL){
struct comand_stack* tempPtr = *stack;
*stack = (*stack) -> next;
free(tempPtr);
}
}
/*
this will add a new line at the end of the editor list (or structure)
*/
void add_line_to_editor(struct line line);
/*
this will add new element to the list of the line chosen with the given text
*/
void add_text_to_line(int line_number, char text[1024], int group_length);
/*
this will add a new element at the end of the move list, with the modified lines as info
*/
void add_new_move(char modified_lines[128]);
/*
this will handle the change command
*/
void change(int start_line, int end_line);
/*
this will handle the delete command
*/
void delete(int start_line, int end_line);
/*
this will handle the print command
*/
void print(int start_line, int end_line);
/*
this will handle the undo command
*/
void undo(int number_of_moves);
/*
this will handle the redo command
*/
void redo(int number_of_moves);
/*
this will handle the split of the command into start and end line
*/
int* get_start_and_end_line_by_command(char command[128], int length);
/*
this will handle the split of the command into number of lines affected
*/
int get_number_of_moves_by_command(char command[128]);
int main ()
{
/*
editor_t * current_line = NULL;
current_line = (editor_t *) malloc(sizeof(editor_t));
*/
char command[128];
int scan = scanf("%s", command);
while (command[0] != 'q')
{
int length = (int)strlen(command);
switch (command[length-1])
{
case 'c':
{
int* s_e_lines = get_start_and_end_line_by_command(command, length);
change(*(s_e_lines), *(s_e_lines+1));
}
break;
case 'd':
{
int* s_e_lines = get_start_and_end_line_by_command(command, length);
delete(*(s_e_lines), *(s_e_lines+1));
}
break;
case 'p':
{
int* s_e_lines = get_start_and_end_line_by_command(command, length);
print(*(s_e_lines), *(s_e_lines+1));
}
case 'u':
{
int number_of_moves = atoi(command);
undo(number_of_moves);
}
case 'r':
{
int number_of_moves = atoi(command);
redo(number_of_moves);
}
break;
default:
break;
}
int scan = scanf("%s", command);
}
}
int* get_start_and_end_line_by_command(char command[128], int length)
{
static int s_e_lines[2];
char* ptr;
ptr = strrchr(command, ',');
int index = ptr-command+1;
s_e_lines[0] = atoi(command);
char endofcommand[length-index];
strncpy(endofcommand, &command[index], length-index);
s_e_lines[1] = atoi(endofcommand);
return s_e_lines;
}
void change(int start_line, int end_line)
{
int group_length = end_line - start_line;
for (int line_number = start_line; line_number < end_line+1; line_number++)
{
char text[1024];
//char* scan = fgets (text, 1024, stdin);
char temp;
int scan = scanf("%c",&temp); // temp statement to clear buffer
scan = scanf("%1024[^\n]",text);
add_text_to_line(line_number, text, group_length);
}
char point[1];
int scan = scanf("%s", point);
if(point[0] != '.'){
//error
}
}
void delete(int start_line, int end_line)
{
for (int line_number = start_line; line_number < end_line+1; line_number++)
{
delete_line(line_number, end_line - start_line);
}
}
void print(int start_line, int end_line)
{
//TODO visit the list from first_line
}
void undo(int number_of_moves)
{
//I think we need to have a redo stack empty for each call of undo (to be verified)
redo_stack = NULL;
for (int i =0 ; i < number_of_moves; i++) {
//if it's a grouped command repeat on the stack for the number of elements in the group
for (int j=0; j < undo_stack -> group_lenght; j++) {
if (undo_stack -> command_type == CHANGE_COMMAND) {
//put the command undone into redo stack
push(undo_stack -> command_type, undo_stack -> line_number, getElementAtLine(undo_stack -> line_number) -> text, undo_stack -> group_lenght, redo_stack);
//get command to undo from undo_stack and undo it
readd_text_to_line(undo_stack -> line_number, undo_stack -> previous_text);
}
if (undo_stack -> command_type == DELETE_COMMAND) {
//put the command undone into redo stack
push(undo_stack -> command_type, undo_stack -> line_number, undo_stack -> previous_text, undo_stack -> group_lenght, redo_stack);
//get command to undo from undo_stack and undo it
readd_line(undo_stack -> line_number, undo_stack -> previous_text);
}
//pop from undostack
pop(undo_stack);
}
}
}
void redo(int number_of_moves)
{
for (int i =0 ; i < number_of_moves; i++) {
//if it's a grouped command repeat on the stack for the number of elements in the group
for (int j=0; j < redo_stack -> group_lenght; j++) {
if (redo_stack -> command_type == CHANGE_COMMAND) {
//get command to undo from undo_stack and undo it
add_text_to_line(redo_stack -> line_number, redo_stack -> previous_text, redo_stack -> group_lenght);
}
if (undo_stack -> command_type == DELETE_COMMAND) {
//get command to undo from undo_stack and undo it
delete_line(redo_stack -> line_number, redo_stack -> group_lenght);
}
//pop from undostack
pop(undo_stack);
}
}
}
line_t* getElementAtLine(int line_number) {
line_t* current_line = first_line;
for (int i = 1; i < line_number; i++) {
if (current_line -> next != NULL) {}
current_line = current_line -> next;
}
return current_line;
}
void add_text_to_line(int line_number, char text[1024], int group_length)
{
line_t* current_line = NULL;
if (first_line == NULL) {
first_line = (line_t*)malloc(sizeof(struct line));
first_line -> next = NULL;
current_line = first_line;
} else {
current_line = getElementAtLine(line_number);
if (current_line == NULL) {
//adding a new line
current_line = (line_t*)malloc(sizeof(struct line));
getElementAtLine(line_number -1) -> next = current_line;
}
}
char previous_text[1024];
strcpy(previous_text, current_line -> text);
strcpy(current_line -> text, text);
push(CHANGE_COMMAND,line_number,previous_text,group_length, undo_stack);
}
void readd_text_to_line(int line_number, char text[1024]) {
line_t* current_line = NULL;
if (first_line == NULL) {
first_line = (line_t*)malloc(sizeof(struct line));
current_line = first_line;
} else {
current_line = getElementAtLine(line_number);
}
strcpy(current_line -> text, text);
}
void delete_line(int line_number, int group_length)
{
line_t* previous_line = getElementAtLine(line_number -1);
line_t* line_to_delete = previous_line -> next;
previous_line -> next = line_to_delete -> next;
char previous_text[1024];
strcpy(previous_text, line_to_delete -> text);
free(line_to_delete);
push(DELETE_COMMAND,line_number,previous_text,group_length, undo_stack);
}
void readd_line(int line_number, char text[1024]) {
line_t* previous_line = getElementAtLine(line_number -1);
line_t* line_to_readd = (line_t*)malloc(sizeof(struct line));
strcpy(line_to_readd -> text, text);
line_to_readd -> next = previous_line -> next;
previous_line -> next = line_to_readd;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment