2023-02-12 00:42:14 -06:00
|
|
|
#include "progs.h"
|
|
|
|
|
|
|
|
#define MAXFILESIZE 0x300000 // 3MB
|
|
|
|
#define MAXLINES 100000
|
|
|
|
#define BLOCKSIZE 0x1000
|
|
|
|
#define BLOCKMASK 0xfff
|
|
|
|
#define BLOCKSHIFT 12
|
|
|
|
#define TOTALBLOCKS (MAXFILESIZE/BLOCKSIZE)
|
|
|
|
uintptr_t lineOffsets[MAXLINES] __attribute__((section(".textbss")));;
|
|
|
|
uintptr_t lineLengths[MAXLINES] __attribute__((section(".textbss")));;
|
|
|
|
uint8_t editedBlocks[TOTALBLOCKS] __attribute__((section(".textbss")));;
|
|
|
|
uint8_t fileBuffer[MAXFILESIZE]
|
|
|
|
__attribute__((aligned(0x1000)))
|
|
|
|
__attribute__((section(".textlatebss")));
|
2023-02-17 06:21:43 -06:00
|
|
|
void TextViewTest(char *path) {
|
2023-02-12 00:42:14 -06:00
|
|
|
uint16_t *vga_text = (uint16_t *)0xb8000;
|
2023-02-17 06:21:43 -06:00
|
|
|
uint32_t fileLen;
|
2023-02-12 00:42:14 -06:00
|
|
|
{
|
|
|
|
uint32_t err;
|
2023-02-17 06:21:43 -06:00
|
|
|
dirent de;
|
|
|
|
err = path_getinfo(path, &de);
|
|
|
|
if (err) {
|
|
|
|
vga_text += printStr("Error getting file info.", vga_text);
|
|
|
|
kbd_wait();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fileLen = de.size;
|
2023-02-14 23:48:11 -06:00
|
|
|
FILE file;
|
|
|
|
err = file_open(&file, path, OPENREAD);
|
2023-02-12 00:42:14 -06:00
|
|
|
if (err) {
|
|
|
|
vga_text += printStr("Open Error: ", vga_text);
|
|
|
|
printDword(err, vga_text);
|
|
|
|
kbd_wait();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// file too large
|
2023-02-14 23:48:11 -06:00
|
|
|
if (fileLen > MAXFILESIZE) {
|
2023-02-12 00:42:14 -06:00
|
|
|
vga_text += printStr("File too large.", vga_text);
|
|
|
|
kbd_wait();
|
|
|
|
return;
|
|
|
|
}
|
2023-02-14 23:48:11 -06:00
|
|
|
if (file_seek(&file, 0)) {
|
2023-02-12 00:42:14 -06:00
|
|
|
vga_text += printStr("Seek Error", vga_text);
|
|
|
|
kbd_wait();
|
|
|
|
return;
|
|
|
|
}
|
2023-02-14 23:48:11 -06:00
|
|
|
uint32_t bytesRead = file_read(&file, fileBuffer, fileLen);
|
|
|
|
if (bytesRead < fileLen) {
|
2023-02-12 00:42:14 -06:00
|
|
|
vga_text += printStr("Read Error: ", vga_text);
|
|
|
|
printDword(err, vga_text);
|
|
|
|
kbd_wait();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint32_t lastLine;
|
|
|
|
{
|
|
|
|
char nl;
|
|
|
|
uint8_t c = 0x0A; // start with a pretend newline
|
|
|
|
uint32_t line = -1; // start a pretend line behind
|
|
|
|
uint32_t lineLen = 0;
|
|
|
|
for (int32_t o = -1; o < (int32_t)fileLen; lineLen++, c = fileBuffer[++o]) {
|
|
|
|
// newline
|
|
|
|
if (c == 0x0A) {
|
|
|
|
lineOffsets[++line] = o;
|
|
|
|
lineLengths[line] = lineLen > 0 ? lineLen : 1;
|
|
|
|
lineLen = 0;
|
|
|
|
}
|
|
|
|
// file too large
|
|
|
|
if (line >= MAXLINES) {
|
|
|
|
vga_text += printStr("File too large.", vga_text);
|
|
|
|
kbd_wait();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lineLengths[line] = lineLen;
|
|
|
|
lastLine = line;
|
|
|
|
}
|
|
|
|
uint32_t currLine = 0;
|
|
|
|
char cont = 1;
|
|
|
|
uint32_t screenSize = 80*25;
|
|
|
|
char redraw = 1;
|
|
|
|
uint32_t linesOnScreen = 0;
|
|
|
|
uint32_t cursorLine = 0;
|
|
|
|
uint32_t cursorLineOffset = 0;
|
|
|
|
char cursorChange = 0;
|
|
|
|
for (;cont;) {
|
|
|
|
if (cursorLine > lastLine) {
|
|
|
|
cursorLine = lastLine;
|
|
|
|
cursorLineOffset = lineLengths[lastLine] - 2;
|
|
|
|
cursorChange = 1;
|
|
|
|
}
|
|
|
|
if (lineLengths[cursorLine+1] == 1 && cursorLineOffset == 0){}
|
|
|
|
else if (cursorLineOffset >= lineLengths[cursorLine+1] - 1) {
|
|
|
|
cursorLineOffset = 0;
|
|
|
|
cursorLine++;
|
|
|
|
cursorChange = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (redraw || cursorChange) {
|
|
|
|
vga_text = (uint16_t *)0xb8000;
|
|
|
|
for (int i = 0; i < screenSize; i++)
|
|
|
|
vga_text[i] = 0x0f00;
|
|
|
|
char pathBuff[22];
|
|
|
|
trimPath((char*)path, pathBuff, sizeof(pathBuff));
|
|
|
|
vga_text += printStr(pathBuff, vga_text);
|
|
|
|
vga_text += 2;
|
|
|
|
vga_text += printDec(currLine, vga_text);
|
|
|
|
vga_text += printChar('/', vga_text);
|
|
|
|
vga_text += printDec(lastLine, vga_text);
|
|
|
|
vga_text += printStr(" Scroll: Up/Down PgUp/PgDown Home/End", vga_text);
|
|
|
|
{
|
|
|
|
const char prnt[] = "Exit: F1";
|
|
|
|
vga_text = &((uint16_t*)0xb8000)[80-sizeof(prnt)+1];
|
|
|
|
vga_text += printStr((char*)prnt, vga_text);
|
|
|
|
}
|
|
|
|
for (vga_text = &((uint16_t*)0xb8000)[84]; vga_text < &((uint16_t*)0xb8000)[screenSize]; vga_text += 80)
|
|
|
|
*(uint8_t*)vga_text = '|';
|
|
|
|
vga_text = &((uint16_t*)0xb8000)[0];
|
|
|
|
uint32_t screenLineOff = 6;
|
|
|
|
uint32_t lineOffset = 0;
|
|
|
|
uint8_t c = 0x0A; // start with a pretend newline
|
|
|
|
uint32_t line = currLine - 1; // start a pretend line behind
|
|
|
|
int32_t o = lineOffsets[currLine]; // the real or fake newline on previous line
|
|
|
|
linesOnScreen = screenSize/80;
|
|
|
|
for (; o < (int32_t)fileLen && vga_text < &((uint16_t*)0xb8000)[screenSize]; c = fileBuffer[++o]) {
|
|
|
|
// newline
|
|
|
|
if (c == 0x0A) {
|
|
|
|
vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
|
|
|
|
line++;
|
|
|
|
lineOffset = 0;
|
|
|
|
{
|
|
|
|
uint16_t *vga_tmp = vga_text;
|
|
|
|
uint16_t decTmp[11];
|
|
|
|
char cnt = printDec(line, decTmp);
|
|
|
|
char off = cnt <= 4 ? 0 : cnt - 4;
|
|
|
|
vga_tmp += 4 - (cnt - off);
|
|
|
|
for (int i = off; i < cnt; i++, vga_tmp++)
|
|
|
|
*(uint8_t*)vga_tmp = (uint8_t)decTmp[i];
|
|
|
|
}
|
|
|
|
vga_text += 6;
|
|
|
|
screenLineOff = 6;
|
|
|
|
if (cursorLine == line && cursorLineOffset == lineOffset) {
|
|
|
|
((uint8_t*)vga_text)[1] = 0xf0;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*(uint8_t*)vga_text = c;
|
|
|
|
if (cursorLine == line && cursorLineOffset == lineOffset) {
|
|
|
|
((uint8_t*)vga_text)[1] = 0xf0;
|
|
|
|
}
|
|
|
|
lineOffset++;
|
|
|
|
vga_text++;
|
|
|
|
screenLineOff++;
|
|
|
|
if (screenLineOff == 80) { // last char
|
|
|
|
vga_text += 6;
|
|
|
|
screenLineOff = 6;
|
|
|
|
linesOnScreen--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
redraw = 0;
|
|
|
|
}
|
|
|
|
uint16_t key = get_scancode();
|
|
|
|
union V86Regs_t regs;
|
|
|
|
FARPTR v86_entry;
|
|
|
|
switch (key & 0xff) {
|
|
|
|
/*case KEY_DOWN: // down
|
|
|
|
if (currLine < lastLine && lineOffsets[currLine+1] < fileLen) {
|
|
|
|
currLine++;
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KEY_UP: // up
|
|
|
|
if ((currLine > 0 && lineOffsets[currLine-1] < fileLen) || currLine == 1) {
|
|
|
|
currLine--;
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
break;*/
|
|
|
|
case KEY_DOWN:
|
|
|
|
cursorLine++;
|
|
|
|
cursorChange = 1;
|
|
|
|
break;
|
|
|
|
case KEY_UP:
|
|
|
|
if (cursorLine > 0) cursorLine--;
|
|
|
|
cursorChange = 1;
|
|
|
|
break;
|
|
|
|
case KEY_LEFT:
|
|
|
|
if (cursorLineOffset > 0) cursorLineOffset--;
|
|
|
|
cursorChange = 1;
|
|
|
|
break;
|
|
|
|
case KEY_RIGHT:
|
|
|
|
cursorLineOffset++;
|
|
|
|
cursorChange = 1;
|
|
|
|
break;
|
|
|
|
case KEY_PGDOWN:
|
|
|
|
if (currLine+(linesOnScreen/2) <= lastLine && lineOffsets[currLine+(linesOnScreen/2)] < fileLen) {
|
|
|
|
currLine += (linesOnScreen/2);
|
|
|
|
redraw = 1;
|
|
|
|
} else goto end;
|
|
|
|
break;
|
|
|
|
case KEY_PGUP:
|
|
|
|
if (currLine > (linesOnScreen/2) && lineOffsets[currLine-(linesOnScreen/2)] < fileLen) {
|
|
|
|
currLine -= (linesOnScreen/2);
|
|
|
|
redraw = 1;
|
|
|
|
} else if (currLine <= (linesOnScreen/2)) {
|
|
|
|
currLine = 0;
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KEY_HOME: home:
|
|
|
|
if (currLine != 0) {
|
|
|
|
currLine = 0;
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KEY_END: end:
|
|
|
|
if (currLine != lastLine) {
|
|
|
|
currLine = lastLine;
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KEY_F1:
|
|
|
|
cont = 0;
|
|
|
|
break;
|
|
|
|
case KEY_F2:
|
|
|
|
if (screenSize != 80*25) {
|
|
|
|
SetVideo25Lines();
|
|
|
|
SetCursorDisabled();
|
|
|
|
screenSize = 80*25;
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KEY_F5:
|
|
|
|
if (screenSize != 80*50) {
|
|
|
|
SetVideo50Lines();
|
|
|
|
SetCursorDisabled();
|
|
|
|
screenSize = 80*50;
|
|
|
|
redraw = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|