#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <readline.h>
void parse_range(char *k, int *l1, int *l2) {
*l1 = 0;
*l2 = 0;
while (k[0] == ' ' || k[0] == '\t') k++;
while (k[0] >= '0' && k[0] <= '9') {
(*l1) *= 10;
(*l1) += (k[0] - '0');
k++;
}
if (k[0] == '-') {
k++;
while (k[0] >= '0' && k[0] <= '9') {
(*l2) *= 10;
(*l2) += (k[0] - '0');
k++;
}
}
if (k[0] != 0) {
*l1 = 0;
}
if (*l2 == 0) *l2 = *l1;
if (*l1 == 0 || *l2 < *l1) {
printf("Invalid range.");
*l1 = 0;
}
}
int main(int argc, char **args) {
int linecount;
char **lines;
int i, j;
readline_history hist;
hist.str = 0; hist.max = 10;
if (args[1] == 0) {
printf("Usage: %s filename\n", args[0]);
} else {
// load file
file_info info;
int e = stat(args[1], &info);
if (e == E_NOT_FOUND) {
printf("File not found. Creating new file.\n");
linecount = 0;
lines = malloc(1 * sizeof(char*));
lines[0] = 0;
} else if (info.type & FT_FILE) {
int f = open(args[1], FM_READ);
char* buff = (char*)malloc(info.size);
read(f, 0, info.size, buff);
close(f);
// count newlines
linecount = 1;
for (i = 0; i < info.size; i++) {
if (buff[i] == '\n') linecount++;
}
lines = malloc(linecount * sizeof(char*));
// copy lines
i = 0;
int p = 0, l = 0;
while (i <= info.size) {
if ((i == info.size && buff[i-1] != 0) || buff[i] == '\n') {
lines[l] = malloc(i - p + 1);
for (j = 0; j < i-p; j++) lines[l][j] = buff[p+j];
lines[l][i-p] = 0;
l++;
p = i+1;
}
i++;
}
while (l < linecount) linecount--;
if (linecount > 0 && lines[linecount-1][0] == 0) {
free(lines[linecount-1]);
linecount--;
}
// free buffer
free(buff);
} else {
printf("%s is not a file. Exiting.\n", args[1]);
return -1;
}
// run
while (lines) {
printf("[%d lines] ", linecount);
char *s = freadline(stdin, &hist);
if (strcmp(s, "q") == 0) {
break;
} else if (strcmp(s, "l") == 0) {
for (i = 0; i < linecount; i++) {
printf("%d\t%s\n", i + 1, lines[i]);
}
} else if (s[0] == 'l') {
int l1, l2;
parse_range(s + 1, &l1, &l2);
if (l1 != 0) {
if (l2 > linecount) {
printf("There are only %d lines.\n", linecount);
} else {
for (i = l1; i <= l2; i++) {
printf("%d\t%s\n", i, lines[i-1]);
}
}
}
} else if (strcmp(s, "w") == 0) {
// calculate buffer size
int buffsz = 0;
for (i = 0; i < linecount; i++) {
buffsz += strlen(lines[i]) + 1;
}
//write buffer
char *buff = malloc(buffsz);
char *p = buff;
for (i = 0; i < linecount; i++) {
for (j = 0; lines[i][j]; j++) {
*(p++) = lines[i][j];
}
*(p++) = '\n';
}
// write buffer
int f = open(args[1], FM_WRITE | FM_TRUNC | FM_CREATE | FT_FILE);
if (f > 0) {
write(f, 0, buffsz, buff);
close(f);
printf("%s written, %d lines, %d characters\n", args[1], linecount, buffsz);
} else {
printf("Error %d in opening %s\n", f, args[1]);
}
free(buff);
} else if (s[0] >= '1' && s[0] <= '9') {
int line = 0;
i = 0;
while (s[i] >= '0' && s[i] <= '9') {
line *= 10;
line += (s[i] - '0');
i++;
}
if(s[i] == ' ' || s[i] == '\t') i++;
char *nl = s + i;
if (line < 1) {
printf("Invalid line number.\n");
continue;
}
if (line > linecount) {
char **lines2 = malloc(line * sizeof(char*));
for (i = 0; i < linecount; i++) {
lines2[i] = lines[i];
}
for (i = linecount; i < line; i++) {
lines2[i] = strdup("");
}
free(lines); //PB
lines = lines2;
linecount = line;
}
free(lines[line-1]);
lines[line-1] = strdup(nl);
} else if (s[0] == 'd') {
int l1, l2;
parse_range(s + 1, &l1, &l2);
if (l1 != 0) {
l1--;
for (i = l1; i < l2; i++) {
free(lines[i]);
}
for (i = l2; i < linecount; i++) {
lines[i - (l2 - l1)] = lines[i];
}
linecount -= (l2 - l1);
}
} else {
printf("Unknown command: %s\n", s);
}
}
}
return 0;
}