Skip to content
Snippets Groups Projects
Commit e4ed0acb authored by John Hodge's avatar John Hodge
Browse files

Usermode - Starting on a text editor

parent 57ffa414
No related merge requests found
# Project: text editor
-include ../Makefile.cfg
OBJ = main.o
BIN = edit
-include ../Makefile.tpl
edit.lin:
gcc main.c -o edit.lin -DUSE_LOCAL=1 -Wall
/*
* Acess2 Text Editor
*/
#if !USE_LOCAL
# include <acess/sys.h> // Needed for IOCtl
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#if USE_LOCAL
# include <sys/ioctl.h>
# include <termios.h>
#else
# include <acess/devices/terminal.h>
#endif
#define MAX_FILES_OPEN 1
// === TYPES ===
typedef struct
{
const char *Filename;
char **LineBuffer;
int FileSize;
int LineCount;
int FirstLine;
int CurrentLine; //!< Currently selected line
int CurrentPos; //!< Position in that line
} tFile;
// === PROTOTYPES ===
void SigINT_Handler(int Signum);
void ExitHandler(void);
int main(int argc, char *argv[]);
int OpenFile(tFile *Dest, const char *Path);
void UpdateDisplayFull(void);
void UpdateDisplayLine(int LineNum);
void UpdateDisplayStatus(void);
void CursorUp(tFile *File);
void CursorDown(tFile *File);
void CursorRight(tFile *File);
void CursorLeft(tFile *File);
void Term_SetPos(int Row, int Col);
// === GLOBALS ===
int giProgramState = 0;
tFile gaFiles[MAX_FILES_OPEN];
tFile *gpCurrentFile;
#if USE_LOCAL
struct termios gOldTermios;
#endif
int giTerminal_Width = 80;
int giTerminal_Height = 25;
// === CODE ===
void SigINT_Handler(int Signum)
{
exit(55);
}
void ExitHandler(void)
{
#if USE_LOCAL
tcsetattr(0, TCSANOW, &gOldTermios);
#endif
printf("\x1B[?1047l");
}
/**
* \fn int main(int argc, char *argv[])
* \brief Entrypoint
*/
int main(int argc, char *argv[])
{
if(argc < 2) {
printf("Usage: edit <file>\n");
return -1;
}
if( OpenFile(&gaFiles[0], argv[1]) ) {
return -1;
}
signal(SIGINT, SigINT_Handler);
atexit(ExitHandler);
// Disable input buffering
#if USE_LOCAL
{
struct termios term;
tcgetattr(0, &gOldTermios);
term = gOldTermios;
term.c_lflag &= ~(ICANON|ECHO);
tcsetattr(0, TCSANOW, &term);
//setbuf(stdin, NULL);
}
#endif
// Go to alternte screen buffer
printf("\x1B[?1047h");
gpCurrentFile = &gaFiles[0];
UpdateDisplayFull();
giProgramState = 1;
while(giProgramState)
{
char ch = 0;
read(0, &ch, 1);
if(ch == '\x1B')
{
read(0, &ch, 1);
switch(ch)
{
case 'A': CursorUp(gpCurrentFile); break;
case 'B': CursorDown(gpCurrentFile); break;
case 'C': CursorRight(gpCurrentFile); break;
case 'D': CursorLeft(gpCurrentFile); break;
case '[':
read(0, &ch, 1);
switch(ch)
{
case 'A': CursorUp(gpCurrentFile); break;
case 'B': CursorDown(gpCurrentFile); break;
case 'C': CursorRight(gpCurrentFile); break;
case 'D': CursorLeft(gpCurrentFile); break;
default:
printf("ch (\\x1B[) = %x\r", ch);
fflush(stdout);
break;
}
break;
default:
printf("ch (\\x1B) = %x\r", ch);
fflush(stdout);
break;
}
// TODO: Move
}
switch(ch)
{
case 'q':
giProgramState = 0;
break;
}
}
return 0;
}
int OpenFile(tFile *Dest, const char *Path)
{
FILE *fp;
char *buffer;
int i, j;
int start;
fp = fopen(Path, "r");
if(!fp) {
fprintf(stderr, "Unable to open %s\n", Path);
return -1;
}
Dest->Filename = Path;
fseek(fp, 0, SEEK_END);
Dest->FileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
buffer = malloc(Dest->FileSize+1);
fread(buffer, Dest->FileSize, 1, fp);
fclose(fp);
buffer[Dest->FileSize] = '\0';
Dest->LineCount = 1;
for( i = 0; i < Dest->FileSize; i ++ )
{
if( buffer[i] == '\n' )
Dest->LineCount ++;
}
Dest->LineBuffer = malloc( Dest->LineCount * sizeof(char*) );
start = 0;
j = 0;
for( i = 0; i < Dest->FileSize; i ++ )
{
if( buffer[i] == '\n' )
{
buffer[i] = '\0';
Dest->LineBuffer[j] = strdup( &buffer[start] );
start = i+1;
j ++;
}
}
Dest->LineBuffer[j] = strdup( &buffer[start] );
free(buffer);
Dest->FirstLine = 0;
Dest->CurrentLine = 0;
Dest->CurrentPos = 0;
return 0;
}
void ShowLine(tFile *File, int LineNum, int X, int Y, int W)
{
int j, k;
char *line;
line = File->LineBuffer[LineNum];
printf("%6i ", LineNum+1);
j = 8;
for( k = 0; j < W-1 && line[k]; j++, k++ )
{
switch( line[k] )
{
case '\t':
printf("\t");
j += 8;
j &= ~7;
break;
default:
if( line[k] < ' ' || line[k] >= 0x7F ) continue;
printf("%c", line[k]);
break;
}
}
for( ; j < W-1; j++ )
printf(" ");
printf("\n");
}
void ShowFile(tFile *File, int X, int Y, int W, int H)
{
int i;
Term_SetPos(Y, X);
for( i = 0; i < H; i ++ )
{
if( File->FirstLine + i >= File->LineCount ) break;
ShowLine( File, File->FirstLine + i, X, Y + i, W );
}
for( ; i < H; i++ )
printf("\n");
}
void UpdateDisplayFull(void)
{
#if USE_LOCAL
{
struct winsize ws;
ioctl(0, TIOCGWINSZ, &ws);
giTerminal_Width = ws.ws_col;
giTerminal_Height = ws.ws_row;
}
#else
giTerminal_Width = ioctl(1, TERM_IOCTL_WIDTH, NULL);
giTerminal_Height = ioctl(1, TERM_IOCTL_HEIGHT, NULL);
#endif
printf("\x1B[2J");
ShowFile(gpCurrentFile, 0, 0, giTerminal_Width, giTerminal_Height - 1);
// Status Line
UpdateDisplayStatus();
Term_SetPos(
gpCurrentFile->CurrentLine-gpCurrentFile->FirstLine,
8 + gpCurrentFile->CurrentPos
);
fflush(stdout);
}
void UpdateDisplayLine(int Line)
{
ShowLine(
gpCurrentFile, Line,
0, Line - gpCurrentFile->FirstLine,
giTerminal_Width );
}
void UpdateDisplayStatus(void)
{
int lastLine = gpCurrentFile->FirstLine + giTerminal_Height - 1;
if( lastLine > gpCurrentFile->LineCount )
lastLine = gpCurrentFile->LineCount;
printf("--- Line %i/%i (showing %i to %i)",
gpCurrentFile->CurrentLine + 1, gpCurrentFile->LineCount,
gpCurrentFile->FirstLine, lastLine);
}
void CursorUp(tFile *File)
{
if( File->CurrentLine > 0 )
{
File->CurrentLine --;
if( File->FirstLine > File->CurrentLine )
{
File->FirstLine = File->CurrentLine;
UpdateDisplayFull();
}
else
{
UpdateDisplayLine(File->CurrentLine + 1);
UpdateDisplayLine(File->CurrentLine);
UpdateDisplayStatus();
}
}
}
void CursorDown(tFile *File)
{
if( File->CurrentLine+1 < File->LineCount )
{
File->CurrentLine ++;
if( File->FirstLine < File->CurrentLine - (giTerminal_Height-2) )
{
File->FirstLine = File->CurrentLine - (giTerminal_Height-2);
UpdateDisplayFull();
}
else
{
UpdateDisplayLine(File->CurrentLine - 1);
UpdateDisplayLine(File->CurrentLine);
UpdateDisplayStatus();
}
}
}
void CursorRight(tFile *File)
{
if( File->CurrentPos > 0 )
{
File->CurrentPos --;
UpdateDisplayLine(File->CurrentLine);
UpdateDisplayStatus();
}
}
void CursorLeft(tFile *File)
{
if( File->LineBuffer[File->CurrentLine][File->CurrentPos+1] )
{
File->CurrentPos --;
UpdateDisplayLine(File->CurrentLine);
UpdateDisplayStatus();
}
}
void Term_SetPos(int Row, int Col)
{
printf("\x1B[%i;%iH", Row+1, Col+1); // Set cursor
fflush(stdout);
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment