# # Software from the book "Inferno Programming with Limbo" # published by John Wiley & Sons, January 2003. # # p. Stanley-Marbell # implement Pled; include "sys.m"; include "draw.m"; include "bufio.m"; include "pled.m"; sys : Sys; bufio : Bufio; FD : import sys; Iobuf : import bufio; cctlfd : ref Sys->FD; curlineidx, cursoridx : int = 0; numlines, mode : int = 0; stdin, stdout : ref Sys->FD; init (nil : ref Draw->Context, argv : list of string) { sys = load Sys Sys->PATH; bufio = load Bufio Bufio->PATH; stdin = sys->fildes(0); stdout = sys->fildes(1); param := tl argv; while (param != nil) { (n, err) := pedit(hd param); if (n != 0) { sys->print("\nPled :: %s\n\n", err); } param = tl param; } cctlfd = sys->open("/dev/consctl", sys->OWRITE); sys->seek(cctlfd, 0, sys->SEEKSTART); sys->write(cctlfd, array of byte "rawoff", len "rawoff"); } pedit (filename : string) : (int, string) { buf := array[1] of byte; consfd : ref FD; key : int = 0; lines : array of Line; tmpstr : string; cctlfd = sys->open("/dev/consctl", sys->OWRITE); if (cctlfd == nil) { return (-1, sys->sprint("Could not open /dev/consctl : %r")); } sys->write(cctlfd, array of byte "rawon", len "rawon"); consfd = sys->open("/dev/cons", sys->OREAD); if (consfd == nil) { return (-1, sys->sprint("Could not open /dev/cons : %r")); } filebuf := bufio->open(filename, sys->OREAD); if (filebuf == nil) { return (-1, sys->sprint("Could not open [%s] : %r", filename)); } # Determine number of lines in input file numlines = 0; while (filebuf.gets('\n') != nil) { numlines++; } filebuf = bufio->open(filename, sys->ORDWR); lines = array [numlines+1] of Line; numlines = 0; while ((tmpstr = filebuf.gets('\n')) != nil) { lines[numlines].str = cleanends(tmpstr); lines[numlines].ntabs = counttabs(tmpstr); numlines++; } # Peruse mode by default mode = 'P'; sys->fprint(stdout, "\n\nFile [%s], [%d] lines total\n\n", filename, numlines); sys->fprint(stdout, "[0][P]%s", lines[curlineidx].str); cursoridx = len lines[curlineidx].str; while (sys->read(consfd, buf, 1) == 1) { key = int buf[0]; case (key | (mode << 8)) { # Ctrl-d : Exit KEY_CTRLD => { sys->fprint(stdout, "\n\n"); return (0, ""); } # "s" or ENTER in peruse mode : Next line KEY_S or KEY_PNEWLINE => { if (curlineidx < numlines-1) { tmp := "[" + string curlineidx + "][ ]"; clear(len lines[curlineidx].str + len tmp + lines[curlineidx].ntabs*(TABLEN-1)); curlineidx++; sys->fprint(stdout, "[%d][%c]%s", curlineidx, mode, lines[curlineidx].str); } } # ENTER in edit mode KEY_ENEWLINE => { if (curlineidx < numlines-1) { tmp := "[" + string curlineidx + "][ ]"; clear(len lines[curlineidx].str + len tmp + lines[curlineidx].ntabs*(TABLEN-1)); curlineidx++; sys->fprint(stdout, "[%d][%c]%s", curlineidx, mode, lines[curlineidx].str); } else { #insert_line(lines, cur_line_index); } } # 'a' : Previous line KEY_A => { if ((curlineidx > 0) && mode != 'E' ) { tmp := "[" + string curlineidx + "][ ]"; clear(len lines[curlineidx].str + len tmp + lines[curlineidx].ntabs*(TABLEN-1)); curlineidx--; sys->fprint(stdout,"[%d][%c]%s", curlineidx, mode, lines[curlineidx].str); } } # ESC : Toggle edit mode KEY_PESC or KEY_EESC => { if (mode == 'P') { mode = 'E'; } else { mode = 'P'; } tmp := "[" + string curlineidx + "][ ]"; clear(len lines[curlineidx].str + len tmp + lines[curlineidx].ntabs*(TABLEN-1)); sys->fprint(stdout, "[%d][%c]%s", curlineidx, mode, lines[curlineidx].str); cursoridx = len lines[curlineidx].str; } # Save KEY_DOT => { save(filebuf, lines); } # Backspace KEY_BACKSPACE => { if (cursoridx >= 1) { sys->fprint(stdout,"\b"); cursoridx--; } } # Tabs KEY_TAB => { sys->fprint(stdout, "%c", TABCHAR); lines[curlineidx].str[cursoridx] = key; cursoridx++; } # List lines KEY_L => { cctlfd = nil; cctlfd = sys->open("/dev/consctl", sys->OWRITE); sys->seek(cctlfd,0, sys->SEEKSTART); sys->write(cctlfd, array of byte "rawoff", len "rawoff"); lbuf := array [Sys->ATOMICIO] of byte; sys->fprint(stdout,"\nLines to List: "); sys->read(stdin, lbuf, len lbuf); (n, llist) := sys->tokenize(string lbuf, " \n\r"); if ( (int hd llist > numlines) || (int hd llist < 0) || (int hd tl tl llist > numlines) || (int hd tl tl llist < int hd llist) || (hd tl llist != "-") ) { if (hd tl llist != "-") { sys->fprint(stdout, "Wrong Format : \"%s\"\n", string lbuf); } else { sys->fprint(stdout, "Out of range. File Contains %d lines.\n", numlines); sys->fprint(stdout, "[%d][%c]%s", curlineidx, mode, lines[curlineidx].str); } } else { start := int hd llist; finish := int hd tl tl llist; sys->fprint(stdout,"\n\n"); for (i := start; i <= finish; i++) { sys->fprint(stdout, "%s\n","|"+ string i +"> "+ lines[i].str); } sys->fprint(stdout,"\n\n"); sys->fprint(stdout,"[%d][%c]%s", curlineidx, mode, lines[curlineidx].str); } sys->seek(cctlfd,0, sys->SEEKSTART); sys->write(cctlfd, array of byte "rawon", len "rawon"); } KEY_N => { sys->fprint(stdout, "\n\nFile Contains %d lines total.\n\n", numlines); sys->fprint(stdout, "[%d][%c]%s", curlineidx, mode, lines[curlineidx].str); } * => { if (mode == 'E') { if (cursoridx < len lines[curlineidx].str) { lines[curlineidx].str[cursoridx] = key; } else { lines[curlineidx].str[len lines[curlineidx].str] = key; } cursoridx++; sys->fprint(stdout,"%c", key); } } } } sys->fprint(stdout,"\n"); return (0, ""); } cleanends(tmpstr : string) : string { CR := max(len tmpstr - 2, 0); LF := max(len tmpstr - 1, 0); if (tmpstr[CR] == '\r') { return tmpstr[: CR]; } else if (tmpstr[LF] == '\n') { return tmpstr[: LF]; } return tmpstr; } counttabs(line : string) : int { ntabs := 0; for (i := 0; i < len line; i++) { if (line[i] == '\t') ntabs++; } return ntabs; } clear(delwidth : int) { delete := string (array [delwidth] of {* => byte '\b'}); blank := string (array [delwidth] of {* => byte ' '}); sys->print("%s", delete); sys->print("%s", blank); sys->print("%s", delete); } save(filebuf : ref Iobuf, lines : array of Line) { filebuf.seek(0, 0); for (i := 0; i < numlines; i++) { # We had stripped the newlines of the ends if (lines[i].str == "\n") { filebuf.puts(lines[i].str); } else { filebuf.puts(lines[i].str+"\n"); } } filebuf.flush(); tmp := "[" + string curlineidx + "][ ]"; clear(len lines[curlineidx].str + len tmp + lines[curlineidx].ntabs*(TABLEN-1)); sys->fprint(stdout, "[%d][%c]%s", curlineidx, 'S', lines[curlineidx].str); } max(a, b : int) : int { if (a > b) { return a; } return b; }