5 # include <acess/sys.h> // Needed for IOCtl
\r
14 # include <sys/ioctl.h>
\r
15 # include <termios.h>
\r
17 # include <acess/devices/terminal.h>
\r
20 #define MAX_FILES_OPEN 1
\r
25 const char *Filename;
\r
31 int CurrentLine; //!< Currently selected line
\r
32 int CurrentPos; //!< Position in that line
\r
35 // === PROTOTYPES ===
\r
36 void SigINT_Handler(int Signum);
\r
37 void ExitHandler(void);
\r
38 int main(int argc, char *argv[]);
\r
39 int OpenFile(tFile *Dest, const char *Path);
\r
40 void UpdateDisplayFull(void);
\r
41 void UpdateDisplayLine(int LineNum);
\r
42 void UpdateDisplayStatus(void);
\r
44 void CursorUp(tFile *File);
\r
45 void CursorDown(tFile *File);
\r
46 void CursorRight(tFile *File);
\r
47 void CursorLeft(tFile *File);
\r
49 void Term_SetPos(int Row, int Col);
\r
52 int giProgramState = 0;
\r
53 tFile gaFiles[MAX_FILES_OPEN];
\r
54 tFile *gpCurrentFile;
\r
56 struct termios gOldTermios;
\r
58 int giTerminal_Width = 80;
\r
59 int giTerminal_Height = 25;
\r
62 void SigINT_Handler(int Signum)
\r
67 void ExitHandler(void)
\r
70 tcsetattr(0, TCSANOW, &gOldTermios);
\r
72 printf("\x1B[?1047l");
\r
76 * \fn int main(int argc, char *argv[])
\r
79 int main(int argc, char *argv[])
\r
83 printf("Usage: edit <file>\n");
\r
87 if( OpenFile(&gaFiles[0], argv[1]) ) {
\r
91 signal(SIGINT, SigINT_Handler);
\r
92 atexit(ExitHandler);
\r
94 // Disable input buffering
\r
97 struct termios term;
\r
98 tcgetattr(0, &gOldTermios);
\r
100 term.c_lflag &= ~(ICANON|ECHO);
\r
101 tcsetattr(0, TCSANOW, &term);
\r
102 //setbuf(stdin, NULL);
\r
106 // Go to alternte screen buffer
\r
107 printf("\x1B[?1047h");
\r
109 gpCurrentFile = &gaFiles[0];
\r
111 UpdateDisplayFull();
\r
113 giProgramState = 1;
\r
115 while(giProgramState)
\r
126 case 'A': CursorUp(gpCurrentFile); break;
\r
127 case 'B': CursorDown(gpCurrentFile); break;
\r
128 case 'C': CursorRight(gpCurrentFile); break;
\r
129 case 'D': CursorLeft(gpCurrentFile); break;
\r
135 case 'A': CursorUp(gpCurrentFile); break;
\r
136 case 'B': CursorDown(gpCurrentFile); break;
\r
137 case 'C': CursorRight(gpCurrentFile); break;
\r
138 case 'D': CursorLeft(gpCurrentFile); break;
\r
140 printf("ch (\\x1B[) = %x\r", ch);
\r
147 printf("ch (\\x1B) = %x\r", ch);
\r
157 giProgramState = 0;
\r
165 int OpenFile(tFile *Dest, const char *Path)
\r
172 fp = fopen(Path, "r");
\r
174 fprintf(stderr, "Unable to open %s\n", Path);
\r
178 Dest->Filename = Path;
\r
180 fseek(fp, 0, SEEK_END);
\r
181 Dest->FileSize = ftell(fp);
\r
182 fseek(fp, 0, SEEK_SET);
\r
184 buffer = malloc(Dest->FileSize+1);
\r
185 fread(buffer, Dest->FileSize, 1, fp);
\r
187 buffer[Dest->FileSize] = '\0';
\r
189 Dest->LineCount = 1;
\r
190 for( i = 0; i < Dest->FileSize; i ++ )
\r
192 if( buffer[i] == '\n' )
\r
193 Dest->LineCount ++;
\r
196 Dest->LineBuffer = malloc( Dest->LineCount * sizeof(char*) );
\r
199 for( i = 0; i < Dest->FileSize; i ++ )
\r
201 if( buffer[i] == '\n' )
\r
204 Dest->LineBuffer[j] = strdup( &buffer[start] );
\r
209 Dest->LineBuffer[j] = strdup( &buffer[start] );
\r
213 Dest->FirstLine = 0;
\r
214 Dest->CurrentLine = 0;
\r
215 Dest->CurrentPos = 0;
\r
220 void ShowLine(tFile *File, int LineNum, int X, int Y, int W)
\r
225 line = File->LineBuffer[LineNum];
\r
226 printf("%6i ", LineNum+1);
\r
228 for( k = 0; j < W-1 && line[k]; j++, k++ )
\r
238 if( line[k] < ' ' || line[k] >= 0x7F ) continue;
\r
239 printf("%c", line[k]);
\r
244 for( ; j < W-1; j++ )
\r
249 void ShowFile(tFile *File, int X, int Y, int W, int H)
\r
254 for( i = 0; i < H; i ++ )
\r
256 if( File->FirstLine + i >= File->LineCount ) break;
\r
257 ShowLine( File, File->FirstLine + i, X, Y + i, W );
\r
259 for( ; i < H; i++ )
\r
263 void UpdateDisplayFull(void)
\r
268 ioctl(0, TIOCGWINSZ, &ws);
\r
269 giTerminal_Width = ws.ws_col;
\r
270 giTerminal_Height = ws.ws_row;
\r
273 giTerminal_Width = ioctl(1, TERM_IOCTL_WIDTH, NULL);
\r
274 giTerminal_Height = ioctl(1, TERM_IOCTL_HEIGHT, NULL);
\r
279 ShowFile(gpCurrentFile, 0, 0, giTerminal_Width, giTerminal_Height - 1);
\r
283 UpdateDisplayStatus();
\r
286 gpCurrentFile->CurrentLine-gpCurrentFile->FirstLine,
\r
287 8 + gpCurrentFile->CurrentPos
\r
292 void UpdateDisplayLine(int Line)
\r
295 gpCurrentFile, Line,
\r
296 0, Line - gpCurrentFile->FirstLine,
\r
297 giTerminal_Width );
\r
300 void UpdateDisplayStatus(void)
\r
302 int lastLine = gpCurrentFile->FirstLine + giTerminal_Height - 1;
\r
304 if( lastLine > gpCurrentFile->LineCount )
\r
305 lastLine = gpCurrentFile->LineCount;
\r
307 printf("--- Line %i/%i (showing %i to %i)",
\r
308 gpCurrentFile->CurrentLine + 1, gpCurrentFile->LineCount,
\r
309 gpCurrentFile->FirstLine, lastLine);
\r
312 void CursorUp(tFile *File)
\r
314 if( File->CurrentLine > 0 )
\r
316 File->CurrentLine --;
\r
317 if( File->FirstLine > File->CurrentLine )
\r
319 File->FirstLine = File->CurrentLine;
\r
320 UpdateDisplayFull();
\r
324 UpdateDisplayLine(File->CurrentLine + 1);
\r
325 UpdateDisplayLine(File->CurrentLine);
\r
326 UpdateDisplayStatus();
\r
331 void CursorDown(tFile *File)
\r
333 if( File->CurrentLine+1 < File->LineCount )
\r
335 File->CurrentLine ++;
\r
336 if( File->FirstLine < File->CurrentLine - (giTerminal_Height-2) )
\r
338 File->FirstLine = File->CurrentLine - (giTerminal_Height-2);
\r
339 UpdateDisplayFull();
\r
343 UpdateDisplayLine(File->CurrentLine - 1);
\r
344 UpdateDisplayLine(File->CurrentLine);
\r
345 UpdateDisplayStatus();
\r
350 void CursorRight(tFile *File)
\r
352 if( File->CurrentPos > 0 )
\r
354 File->CurrentPos --;
\r
355 UpdateDisplayLine(File->CurrentLine);
\r
356 UpdateDisplayStatus();
\r
360 void CursorLeft(tFile *File)
\r
362 if( File->LineBuffer[File->CurrentLine][File->CurrentPos+1] )
\r
364 File->CurrentPos --;
\r
365 UpdateDisplayLine(File->CurrentLine);
\r
366 UpdateDisplayStatus();
\r
370 void Term_SetPos(int Row, int Col)
\r
372 printf("\x1B[%i;%iH", Row+1, Col+1); // Set cursor
\r