start adding indentation support
This commit is contained in:
1 parent
f7d319ad09
commit
ce0ee47558
8 files changed
+601
-46
No files matched your search
@@ -1 +1,3 @@
|
|||||||
char programName[] = "My Text Editor";
|
char programName[] = "My Text Editor";
|
||||||
|
|
||||||
|
int tabSize = 4;
|
||||||
@@ -2,5 +2,6 @@
|
|||||||
#define CONFIG_H
|
#define CONFIG_H
|
||||||
|
|
||||||
extern char programName[];
|
extern char programName[];
|
||||||
|
extern int tabSize;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "lengths.h"
|
#include "lengths.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
struct lineAndCharNum getLineAndCharNum(char *content)
|
struct lineAndCharNum getLineAndCharNum(char *content)
|
||||||
{
|
{
|
||||||
@@ -40,6 +41,41 @@ int lineLength(char *content, int cursor_y)
|
|||||||
return across;
|
return across;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int indent(char *content, int cursor_y, int cursor_x)
|
||||||
|
{
|
||||||
|
int numLines = 0;
|
||||||
|
int numChars = strlen(content);
|
||||||
|
int i = 0;
|
||||||
|
if (cursor_y != 0)
|
||||||
|
{
|
||||||
|
for (; i < numChars; i++)
|
||||||
|
{
|
||||||
|
if (content[i] == '\n')
|
||||||
|
{
|
||||||
|
numLines++;
|
||||||
|
if (numLines == cursor_y)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
int indent = 0;
|
||||||
|
for (int j = i; j < numChars; j++)
|
||||||
|
{
|
||||||
|
if (content[j] == ' ' && indent < cursor_x)
|
||||||
|
{
|
||||||
|
indent++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return indent;
|
||||||
|
}
|
||||||
|
|
||||||
int cursorToCharPos(char *content, int cursor_x, int cursor_y)
|
int cursorToCharPos(char *content, int cursor_x, int cursor_y)
|
||||||
{
|
{
|
||||||
if (cursor_y == 0)
|
if (cursor_y == 0)
|
||||||
|
|||||||
@@ -13,4 +13,6 @@ int lineLength(char *content, int cursor_y);
|
|||||||
|
|
||||||
int cursorToCharPos(char *content, int cursor_x, int cursor_y);
|
int cursorToCharPos(char *content, int cursor_x, int cursor_y);
|
||||||
|
|
||||||
|
int indent(char *content, int cursor_y, int cursor_x);
|
||||||
|
|
||||||
#endif // LENGTHS_H
|
#endif // LENGTHS_H
|
||||||
+115
-33
@@ -13,9 +13,10 @@
|
|||||||
|
|
||||||
int openFile(char *Path)
|
int openFile(char *Path)
|
||||||
{
|
{
|
||||||
char *path = malloc(strlen(Path) + 1);
|
char *path = malloc((sizeof(Path) / sizeof(char *)) + 1);
|
||||||
char *message = malloc(1);
|
char *message = malloc(1);
|
||||||
message[0] = '\0';
|
message[0] = '\0';
|
||||||
|
int showMessage = 0;
|
||||||
strcpy(path, Path);
|
strcpy(path, Path);
|
||||||
ESCDELAY = 0;
|
ESCDELAY = 0;
|
||||||
char *content = malloc(1);
|
char *content = malloc(1);
|
||||||
@@ -23,8 +24,7 @@ int openFile(char *Path)
|
|||||||
|
|
||||||
if (strlen(path) != 0)
|
if (strlen(path) != 0)
|
||||||
{
|
{
|
||||||
FILE *fptr;
|
FILE *fptr = fopen(path, "r");
|
||||||
fptr = fopen(path, "r");
|
|
||||||
if (fptr != NULL)
|
if (fptr != NULL)
|
||||||
{
|
{
|
||||||
// Read the contents of the file into the content variable
|
// Read the contents of the file into the content variable
|
||||||
@@ -37,6 +37,11 @@ int openFile(char *Path)
|
|||||||
fclose(fptr);
|
fclose(fptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *myMessage = "New File";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
}
|
||||||
char *content_COPY = malloc(strlen(content) + 1);
|
char *content_COPY = malloc(strlen(content) + 1);
|
||||||
strcpy(content_COPY, content);
|
strcpy(content_COPY, content);
|
||||||
// path = malloc(100);
|
// path = malloc(100);
|
||||||
@@ -44,7 +49,7 @@ int openFile(char *Path)
|
|||||||
char *command = malloc(1);
|
char *command = malloc(1);
|
||||||
command[0] = '\0';
|
command[0] = '\0';
|
||||||
|
|
||||||
struct FileData fileData = {&path, &content, &command, &mode, 0, 0, 0, 0, 0};
|
struct FileData fileData = {&path, &content, &command, &mode, &message, &showMessage, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
initscr();
|
initscr();
|
||||||
@@ -60,10 +65,15 @@ int openFile(char *Path)
|
|||||||
|
|
||||||
int choice;
|
int choice;
|
||||||
char *newContent;
|
char *newContent;
|
||||||
|
char *myMessage;
|
||||||
|
int lineIndent;
|
||||||
int running = 1;
|
int running = 1;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
choice = getch(); // Get user input
|
choice = getch(); // Get user input
|
||||||
|
int isPrintable = isprint(choice);
|
||||||
|
if (isPrintable)
|
||||||
|
showMessage = 0;
|
||||||
// sprintf(path, "%s, %02X", path, choice);
|
// sprintf(path, "%s, %02X", path, choice);
|
||||||
int stop = 0;
|
int stop = 0;
|
||||||
if (mode != 2)
|
if (mode != 2)
|
||||||
@@ -91,15 +101,19 @@ int openFile(char *Path)
|
|||||||
switch (choice)
|
switch (choice)
|
||||||
{
|
{
|
||||||
case 10:
|
case 10:
|
||||||
newContent = malloc(strlen(content) + 2);
|
lineIndent = indent(content, fileData.cursor_y, fileData.cursor_x);
|
||||||
strncpy(newContent, content, cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y));
|
newContent = malloc(strlen(content) + lineIndent + 1);
|
||||||
newContent[cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y)] = '\n';
|
int cursorPos = cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y);
|
||||||
strncpy(newContent + cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y) + 1, content + cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y), strlen(content) - cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y));
|
strncpy(newContent, content, cursorPos);
|
||||||
newContent[strlen(content) + 1] = '\0';
|
newContent[cursorPos] = '\n';
|
||||||
|
for (int i = 0; i < lineIndent; i++)
|
||||||
|
newContent[cursorPos + i + 1] = ' ';
|
||||||
|
strncpy(newContent + cursorPos + lineIndent + 1, content + cursorPos, strlen(content) - cursorPos);
|
||||||
|
newContent[strlen(content) + cursorPos + lineIndent + 1] = '\0';
|
||||||
free(content);
|
free(content);
|
||||||
content = newContent;
|
content = newContent;
|
||||||
fileData.cursor_y++;
|
fileData.cursor_y++;
|
||||||
fileData.cursor_x = 0;
|
fileData.cursor_x = lineIndent;
|
||||||
across = 0;
|
across = 0;
|
||||||
break;
|
break;
|
||||||
case 27:
|
case 27:
|
||||||
@@ -109,19 +123,41 @@ int openFile(char *Path)
|
|||||||
case 0x7F:
|
case 0x7F:
|
||||||
if (strlen(content) > 0)
|
if (strlen(content) > 0)
|
||||||
{
|
{
|
||||||
|
int toRemove = 1;
|
||||||
|
|
||||||
|
int lineIndent = indent(content, fileData.cursor_y, fileData.cursor_x);
|
||||||
|
if (lineIndent == fileData.cursor_x)
|
||||||
|
{
|
||||||
|
int inTab = lineIndent % tabSize;
|
||||||
|
if (inTab == 0)
|
||||||
|
{
|
||||||
|
toRemove = tabSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toRemove = inTab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileData.cursor_x < toRemove)
|
||||||
|
toRemove = fileData.cursor_x;
|
||||||
|
|
||||||
|
if (toRemove < 1)
|
||||||
|
toRemove = 1;
|
||||||
|
|
||||||
int cursorPos = cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y);
|
int cursorPos = cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y);
|
||||||
if (cursorPos == 0)
|
if (cursorPos == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int length = lineLength(content, fileData.cursor_y - 1);
|
int length = lineLength(content, fileData.cursor_y - toRemove);
|
||||||
char *newContent = malloc(strlen(content));
|
newContent = malloc(strlen(content));
|
||||||
strncpy(newContent, content, cursorPos - 1);
|
strncpy(newContent, content, cursorPos - toRemove);
|
||||||
strncpy(newContent + cursorPos - 1, content + cursorPos, strlen(content) - cursorPos);
|
strncpy(newContent + cursorPos - toRemove, content + cursorPos, strlen(content) - cursorPos);
|
||||||
newContent[strlen(content) - 1] = '\0';
|
newContent[strlen(content) - toRemove] = '\0';
|
||||||
free(content);
|
free(content);
|
||||||
content = newContent;
|
content = newContent;
|
||||||
fileData.cursor_x--;
|
fileData.cursor_x -= toRemove;
|
||||||
if (fileData.cursor_x < 0 && fileData.cursor_y > 0)
|
if (fileData.cursor_x < 0 && fileData.cursor_y > 0)
|
||||||
{
|
{
|
||||||
fileData.cursor_y--;
|
fileData.cursor_y--;
|
||||||
@@ -131,15 +167,15 @@ int openFile(char *Path)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
newContent = malloc(strlen(content) + 2);
|
newContent = malloc(strlen(content) + tabSize);
|
||||||
strncpy(newContent, content, cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y));
|
strncpy(newContent, content, cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y));
|
||||||
newContent[cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y)] = ' ';
|
for (int i = 0; i < tabSize; i++)
|
||||||
newContent[cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y) + 1] = ' ';
|
newContent[cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y) + i] = ' ';
|
||||||
strncpy(newContent + cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y) + 2, content + cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y), strlen(content) - cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y));
|
strncpy(newContent + cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y) + tabSize, content + cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y), strlen(content) - cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y));
|
||||||
newContent[strlen(content) + 2] = '\0';
|
newContent[strlen(content) + tabSize] = '\0';
|
||||||
free(content);
|
free(content);
|
||||||
content = newContent;
|
content = newContent;
|
||||||
fileData.cursor_x += 2;
|
fileData.cursor_x += tabSize;
|
||||||
across = fileData.cursor_x;
|
across = fileData.cursor_x;
|
||||||
break;
|
break;
|
||||||
case 0x17:
|
case 0x17:
|
||||||
@@ -151,7 +187,7 @@ int openFile(char *Path)
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
char *newContent = malloc(strlen(content));
|
newContent = malloc(strlen(content));
|
||||||
strncpy(newContent, content, cursorPos);
|
strncpy(newContent, content, cursorPos);
|
||||||
strncpy(newContent + cursorPos, content + cursorPos + 1, strlen(content) - cursorPos);
|
strncpy(newContent + cursorPos, content + cursorPos + 1, strlen(content) - cursorPos);
|
||||||
newContent[strlen(content) - 1] = '\0';
|
newContent[strlen(content) - 1] = '\0';
|
||||||
@@ -161,11 +197,10 @@ int openFile(char *Path)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (isprint(choice))
|
if (isPrintable)
|
||||||
{
|
{
|
||||||
// sprintf(path, "%s, %02X", path, choice);
|
|
||||||
int cursorPos = cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y);
|
int cursorPos = cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y);
|
||||||
char *newContent = malloc(strlen(content) + 2);
|
newContent = malloc(strlen(content) + 2);
|
||||||
strncpy(newContent, content, cursorPos);
|
strncpy(newContent, content, cursorPos);
|
||||||
newContent[cursorPos] = choice;
|
newContent[cursorPos] = choice;
|
||||||
strncpy(newContent + cursorPos + 1, content + cursorPos, strlen(content) - cursorPos);
|
strncpy(newContent + cursorPos + 1, content + cursorPos, strlen(content) - cursorPos);
|
||||||
@@ -208,11 +243,21 @@ int openFile(char *Path)
|
|||||||
{
|
{
|
||||||
fwrite(content, 1, strlen(content), fptr);
|
fwrite(content, 1, strlen(content), fptr);
|
||||||
fclose(fptr);
|
fclose(fptr);
|
||||||
|
content_COPY = realloc(content_COPY, strlen(content) + 1);
|
||||||
|
strcpy(content_COPY, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (strlen(command) == 1 || command[1] != 'q')
|
if (strlen(command) == 1 || command[1] != 'q')
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
|
if ((strlen(content) != 0 && strcmp(content, content_COPY) != 0) && (strlen(command) == 1 || command[1] != '!'))
|
||||||
|
{
|
||||||
|
char *myMessage = "No write since last change (add ! to override)";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
running = 0;
|
running = 0;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
@@ -231,6 +276,13 @@ int openFile(char *Path)
|
|||||||
strcpy(content_COPY, content);
|
strcpy(content_COPY, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *myMessage = "No path specified";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if (strlen(command) > 2)
|
if (strlen(command) > 2)
|
||||||
@@ -258,7 +310,14 @@ int openFile(char *Path)
|
|||||||
content = realloc(content, 1);
|
content = realloc(content, 1);
|
||||||
content[0] = '\0';
|
content[0] = '\0';
|
||||||
}
|
}
|
||||||
fileData = (struct FileData){&path, &content, &command, &mode, 0, 0, 0, 0, 0};
|
fileData = (struct FileData){&path, &content, &command, &mode, &message, &showMessage, 0, 0, 0, 0, 0};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *myMessage = "No path specified";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
@@ -268,6 +327,17 @@ int openFile(char *Path)
|
|||||||
strncpy(line, command + 2, strlen(command) - 2);
|
strncpy(line, command + 2, strlen(command) - 2);
|
||||||
line[strlen(command) - 2] = '\0';
|
line[strlen(command) - 2] = '\0';
|
||||||
int lineNum = atoi(line);
|
int lineNum = atoi(line);
|
||||||
|
if (lineNum < 0)
|
||||||
|
{
|
||||||
|
if (fileData.numLines + lineNum < 0)
|
||||||
|
{
|
||||||
|
lineNum = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineNum = fileData.numLines + lineNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
int numLines = 0;
|
int numLines = 0;
|
||||||
int numChars = strlen(content);
|
int numChars = strlen(content);
|
||||||
int i;
|
int i;
|
||||||
@@ -282,11 +352,22 @@ int openFile(char *Path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fileData.cursor_y = numLines - 1;
|
fileData.cursor_y = numLines;
|
||||||
fileData.cursor_x = 0;
|
fileData.cursor_x = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *myMessage = "No line specified";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
myMessage = "Invalid command";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,12 +376,13 @@ int openFile(char *Path)
|
|||||||
mode = 0;
|
mode = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (isprint(choice))
|
if (isPrintable)
|
||||||
{
|
{
|
||||||
char *newCommand = malloc(strlen(command) + 2);
|
int length = strlen(command);
|
||||||
strncpy(newCommand, command, strlen(command));
|
char *newCommand = malloc(length + 2);
|
||||||
newCommand[strlen(command)] = choice;
|
strncpy(newCommand, command, length);
|
||||||
newCommand[strlen(command) + 1] = '\0';
|
newCommand[length] = choice;
|
||||||
|
newCommand[length + 1] = '\0';
|
||||||
free(command);
|
free(command);
|
||||||
command = newCommand;
|
command = newCommand;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ struct FileData
|
|||||||
char **content;
|
char **content;
|
||||||
char **command;
|
char **command;
|
||||||
int *mode;
|
int *mode;
|
||||||
|
char **message;
|
||||||
|
int *showMessage;
|
||||||
int cursor_x;
|
int cursor_x;
|
||||||
int cursor_y;
|
int cursor_y;
|
||||||
int scroll;
|
int scroll;
|
||||||
|
|||||||
@@ -124,20 +124,27 @@ void render(struct FileData fileData)
|
|||||||
printw("═");
|
printw("═");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (*fileData.mode)
|
if (*fileData.showMessage)
|
||||||
{
|
{
|
||||||
case 0:
|
printw("%s", *fileData.message);
|
||||||
printw("Normal Mode");
|
}
|
||||||
break;
|
else
|
||||||
case 1:
|
{
|
||||||
printw("Insert Mode");
|
switch (*fileData.mode)
|
||||||
break;
|
{
|
||||||
case 2:
|
case 0:
|
||||||
printw(":%s", *fileData.command);
|
printw("Normal Mode");
|
||||||
break;
|
break;
|
||||||
default:
|
case 1:
|
||||||
printw("Unknown Mode");
|
printw("Insert Mode");
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
|
printw(":%s", *fileData.command);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printw("Unknown Mode");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch (*fileData.mode)
|
switch (*fileData.mode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,423 @@
|
|||||||
|
#include "openFile.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "cursorMovement.h"
|
||||||
|
#include "lengths.h"
|
||||||
|
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
|
int openFile(char *Path)
|
||||||
|
{
|
||||||
|
char *path = malloc((sizeof(Path) / sizeof(char *)) + 1);
|
||||||
|
char *message = malloc(1);
|
||||||
|
message[0] = '\0';
|
||||||
|
int showMessage = 0;
|
||||||
|
strcpy(path, Path);
|
||||||
|
ESCDELAY = 0;
|
||||||
|
char *content = malloc(1);
|
||||||
|
content[0] = '\0';
|
||||||
|
|
||||||
|
if (strlen(path) != 0)
|
||||||
|
{
|
||||||
|
FILE *fptr = fopen(path, "r");
|
||||||
|
if (fptr != NULL)
|
||||||
|
{
|
||||||
|
// Read the contents of the file into the content variable
|
||||||
|
fseek(fptr, 0, SEEK_END);
|
||||||
|
long fsize = ftell(fptr);
|
||||||
|
fseek(fptr, 0, SEEK_SET);
|
||||||
|
content = realloc(content, fsize + 1);
|
||||||
|
fread(content, 1, fsize, fptr);
|
||||||
|
content[fsize] = 0;
|
||||||
|
fclose(fptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *myMessage = "New File";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
}
|
||||||
|
char *content_COPY = malloc(strlen(content) + 1);
|
||||||
|
strcpy(content_COPY, content);
|
||||||
|
// path = malloc(100);
|
||||||
|
int mode = 0;
|
||||||
|
char *command = malloc(1);
|
||||||
|
command[0] = '\0';
|
||||||
|
|
||||||
|
struct FileData fileData = {&path, &content, &command, &mode, &message, &showMessage, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
initscr();
|
||||||
|
cbreak();
|
||||||
|
keypad(stdscr, TRUE);
|
||||||
|
|
||||||
|
struct lineAndCharNum lineAndCharNum = getLineAndCharNum(content);
|
||||||
|
fileData.numLines = lineAndCharNum.lineNum;
|
||||||
|
fileData.numChars = lineAndCharNum.charNum;
|
||||||
|
render(fileData);
|
||||||
|
|
||||||
|
int across = 0;
|
||||||
|
|
||||||
|
int choice;
|
||||||
|
char *newContent;
|
||||||
|
char *myMessage;
|
||||||
|
int lineIndent;
|
||||||
|
int running = 1;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
choice = getch(); // Get user input
|
||||||
|
int isPrintable = isprint(choice);
|
||||||
|
if (isPrintable)
|
||||||
|
showMessage = 0;
|
||||||
|
// sprintf(path, "%s, %02X", path, choice);
|
||||||
|
int stop = 0;
|
||||||
|
if (mode != 2)
|
||||||
|
{
|
||||||
|
cursorMovement(choice, &fileData, &content, &across, &stop);
|
||||||
|
}
|
||||||
|
if (!stop)
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
switch (choice)
|
||||||
|
{
|
||||||
|
case ':':
|
||||||
|
mode = 2;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
mode = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
switch (choice)
|
||||||
|
{
|
||||||
|
case 10:
|
||||||
|
lineIndent = indent(content, fileData.cursor_y, fileData.cursor_x);
|
||||||
|
newContent = malloc(strlen(content) + lineIndent + 1);
|
||||||
|
int cursorPos = cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y);
|
||||||
|
strncpy(newContent, content, cursorPos);
|
||||||
|
newContent[cursorPos] = '\n';
|
||||||
|
for (int i = 0; i < lineIndent; i++)
|
||||||
|
newContent[cursorPos + i + 1] = ' ';
|
||||||
|
strncpy(newContent + cursorPos + lineIndent + 1, content + cursorPos, strlen(content) - cursorPos);
|
||||||
|
newContent[strlen(content) + cursorPos + lineIndent + 1] = '\0';
|
||||||
|
free(content);
|
||||||
|
content = newContent;
|
||||||
|
fileData.cursor_y++;
|
||||||
|
fileData.cursor_x = lineIndent;
|
||||||
|
across = 0;
|
||||||
|
break;
|
||||||
|
case 27:
|
||||||
|
mode = 0;
|
||||||
|
break;
|
||||||
|
case KEY_BACKSPACE:
|
||||||
|
case 0x7F:
|
||||||
|
if (strlen(content) > 0)
|
||||||
|
{
|
||||||
|
int toRemove = 1;
|
||||||
|
|
||||||
|
int lineIndent = indent(content, fileData.cursor_y, fileData.cursor_x);
|
||||||
|
if (lineIndent == fileData.cursor_x)
|
||||||
|
{
|
||||||
|
int inTab = lineIndent % tabSize;
|
||||||
|
if (inTab == 0)
|
||||||
|
{
|
||||||
|
toRemove = tabSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toRemove = inTab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileData.cursor_x < toRemove)
|
||||||
|
toRemove = fileData.cursor_x;
|
||||||
|
|
||||||
|
if (toRemove < 1)
|
||||||
|
toRemove = 1;
|
||||||
|
|
||||||
|
int cursorPos = cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y);
|
||||||
|
if (cursorPos == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int length = lineLength(content, fileData.cursor_y - toRemove);
|
||||||
|
newContent = malloc(strlen(content));
|
||||||
|
strncpy(newContent, content, cursorPos - toRemove);
|
||||||
|
strncpy(newContent + cursorPos - toRemove, content + cursorPos, strlen(content) - cursorPos);
|
||||||
|
newContent[strlen(content) - toRemove] = '\0';
|
||||||
|
free(content);
|
||||||
|
content = newContent;
|
||||||
|
fileData.cursor_x -= toRemove;
|
||||||
|
if (fileData.cursor_x < 0 && fileData.cursor_y > 0)
|
||||||
|
{
|
||||||
|
fileData.cursor_y--;
|
||||||
|
fileData.cursor_x = length;
|
||||||
|
}
|
||||||
|
across = fileData.cursor_x;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
newContent = malloc(strlen(content) + tabSize);
|
||||||
|
strncpy(newContent, content, cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y));
|
||||||
|
for (int i = 0; i < tabSize; i++)
|
||||||
|
newContent[cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y) + i] = ' ';
|
||||||
|
strncpy(newContent + cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y) + tabSize, content + cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y), strlen(content) - cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y));
|
||||||
|
newContent[strlen(content) + tabSize] = '\0';
|
||||||
|
free(content);
|
||||||
|
content = newContent;
|
||||||
|
fileData.cursor_x += tabSize;
|
||||||
|
across = fileData.cursor_x;
|
||||||
|
break;
|
||||||
|
case 0x17:
|
||||||
|
case KEY_DC:
|
||||||
|
if (strlen(content) > 0)
|
||||||
|
{
|
||||||
|
int cursorPos = cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y);
|
||||||
|
if (cursorPos == (int)strlen(content))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
newContent = malloc(strlen(content));
|
||||||
|
strncpy(newContent, content, cursorPos);
|
||||||
|
strncpy(newContent + cursorPos, content + cursorPos + 1, strlen(content) - cursorPos);
|
||||||
|
newContent[strlen(content) - 1] = '\0';
|
||||||
|
free(content);
|
||||||
|
content = newContent;
|
||||||
|
across = fileData.cursor_x;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (isPrintable)
|
||||||
|
{
|
||||||
|
int cursorPos = cursorToCharPos(content, fileData.cursor_x, fileData.cursor_y);
|
||||||
|
newContent = malloc(strlen(content) + 2);
|
||||||
|
strncpy(newContent, content, cursorPos);
|
||||||
|
newContent[cursorPos] = choice;
|
||||||
|
strncpy(newContent + cursorPos + 1, content + cursorPos, strlen(content) - cursorPos);
|
||||||
|
newContent[strlen(content) + 1] = '\0';
|
||||||
|
free(content);
|
||||||
|
content = newContent;
|
||||||
|
fileData.cursor_x++;
|
||||||
|
across = fileData.cursor_x;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
switch (choice)
|
||||||
|
{
|
||||||
|
case 27:
|
||||||
|
mode = 0;
|
||||||
|
break;
|
||||||
|
case KEY_BACKSPACE:
|
||||||
|
case 0x7F:
|
||||||
|
if (strlen(command) > 0)
|
||||||
|
{
|
||||||
|
char *newCommand = malloc(strlen(command));
|
||||||
|
strncpy(newCommand, command, strlen(command) - 1);
|
||||||
|
newCommand[strlen(command) - 1] = '\0';
|
||||||
|
free(command);
|
||||||
|
command = newCommand;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
|
||||||
|
switch (command[0])
|
||||||
|
{
|
||||||
|
case 'w':
|
||||||
|
if (strlen(path) != 0)
|
||||||
|
{
|
||||||
|
FILE *fptr;
|
||||||
|
fptr = fopen(path, "w");
|
||||||
|
if (fptr != NULL)
|
||||||
|
{
|
||||||
|
fwrite(content, 1, strlen(content), fptr);
|
||||||
|
fclose(fptr);
|
||||||
|
content_COPY = realloc(content_COPY, strlen(content) + 1);
|
||||||
|
strcpy(content_COPY, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strlen(command) == 1 || command[1] != 'q')
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
if ((strlen(content) != 0 && strcmp(content, content_COPY) != 0) && (strlen(command) == 1 || command[1] != '!'))
|
||||||
|
{
|
||||||
|
char *myMessage = "No write since last change (add ! to override)";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
running = 0;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if (strlen(command) > 2)
|
||||||
|
{
|
||||||
|
path = realloc(path, strlen(command) - 2);
|
||||||
|
strncpy(path, command + 2, strlen(command) - 2);
|
||||||
|
path[strlen(command) - 2] = '\0';
|
||||||
|
FILE *fptr;
|
||||||
|
fptr = fopen(path, "w");
|
||||||
|
if (fptr != NULL)
|
||||||
|
{
|
||||||
|
fwrite(content, 1, strlen(content), fptr);
|
||||||
|
fclose(fptr);
|
||||||
|
content_COPY = realloc(content_COPY, strlen(content) + 1);
|
||||||
|
strcpy(content_COPY, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *myMessage = "No path specified";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
if (strlen(command) > 2)
|
||||||
|
{
|
||||||
|
char *newPath = malloc(strlen(command) - 2);
|
||||||
|
strncpy(newPath, command + 2, strlen(command) - 2);
|
||||||
|
newPath[strlen(command) - 2] = '\0';
|
||||||
|
FILE *fptr;
|
||||||
|
fptr = fopen(newPath, "r");
|
||||||
|
if (fptr != NULL)
|
||||||
|
{
|
||||||
|
// Read the contents of the file into the content variable
|
||||||
|
fseek(fptr, 0, SEEK_END);
|
||||||
|
long fsize = ftell(fptr);
|
||||||
|
fseek(fptr, 0, SEEK_SET);
|
||||||
|
content = realloc(content, fsize + 1);
|
||||||
|
fread(content, 1, fsize, fptr);
|
||||||
|
content[fsize] = 0;
|
||||||
|
fclose(fptr);
|
||||||
|
free(path);
|
||||||
|
path = newPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
content = realloc(content, 1);
|
||||||
|
content[0] = '\0';
|
||||||
|
}
|
||||||
|
fileData = (struct FileData){&path, &content, &command, &mode, &message, &showMessage, 0, 0, 0, 0, 0};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *myMessage = "No path specified";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
if (strlen(command) > 2)
|
||||||
|
{
|
||||||
|
char *line = malloc(strlen(command) - 2);
|
||||||
|
strncpy(line, command + 2, strlen(command) - 2);
|
||||||
|
line[strlen(command) - 2] = '\0';
|
||||||
|
int lineNum = atoi(line);
|
||||||
|
if (lineNum < 0)
|
||||||
|
{
|
||||||
|
if (fileData.numLines + lineNum < 0)
|
||||||
|
{
|
||||||
|
lineNum = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineNum = fileData.numLines + lineNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int numLines = 0;
|
||||||
|
int numChars = strlen(content);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < numChars; i++)
|
||||||
|
{
|
||||||
|
if (content[i] == '\n')
|
||||||
|
{
|
||||||
|
numLines++;
|
||||||
|
if (numLines == lineNum)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileData.cursor_y = numLines;
|
||||||
|
fileData.cursor_x = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *myMessage = "No line specified";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
myMessage = "Invalid command";
|
||||||
|
message = realloc(message, strlen(myMessage) + 1);
|
||||||
|
strcpy(message, myMessage);
|
||||||
|
showMessage = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
command = realloc(command, 1);
|
||||||
|
command[0] = '\0';
|
||||||
|
mode = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (isPrintable)
|
||||||
|
{
|
||||||
|
int length = strlen(command);
|
||||||
|
char *newCommand = malloc(length + 2);
|
||||||
|
strncpy(newCommand, command, length);
|
||||||
|
newCommand[length] = choice;
|
||||||
|
newCommand[length + 1] = '\0';
|
||||||
|
free(command);
|
||||||
|
command = newCommand;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!running)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fileData.cursor_y < fileData.scroll)
|
||||||
|
{
|
||||||
|
fileData.scroll = fileData.cursor_y;
|
||||||
|
}
|
||||||
|
if (fileData.cursor_y - (LINES - 4) >= fileData.scroll)
|
||||||
|
{
|
||||||
|
fileData.scroll = fileData.cursor_y - (LINES - 4) + 1;
|
||||||
|
}
|
||||||
|
lineAndCharNum = getLineAndCharNum(content);
|
||||||
|
fileData.numLines = lineAndCharNum.lineNum;
|
||||||
|
fileData.numChars = lineAndCharNum.charNum;
|
||||||
|
render(fileData); // Re-render the menu
|
||||||
|
}
|
||||||
|
|
||||||
|
free(content);
|
||||||
|
free(command);
|
||||||
|
free(content_COPY);
|
||||||
|
free(path);
|
||||||
|
free(message);
|
||||||
|
// Clean up and exit ncurses
|
||||||
|
endwin();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user