Saving and backspacing
This commit is contained in:
parent
061ddbc5b5
commit
e14432eae4
126
kilo.c
126
kilo.c
@ -6,6 +6,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
@ -19,7 +20,8 @@
|
||||
/*** defines ***/
|
||||
|
||||
#define KILO_VERSION "0.0.1"
|
||||
#define KILO_TAB_STOP 8
|
||||
#define KILO_TAB_STOP 4
|
||||
#define KILO_QUIT_TIMES 3
|
||||
|
||||
#define CTRL_KEY(k) ((k) & 0x1f)
|
||||
|
||||
@ -54,6 +56,7 @@ struct editorConfig {
|
||||
int screencols;
|
||||
int numrows;
|
||||
erow *row;
|
||||
int dirty;
|
||||
char *filename;
|
||||
char statusmsg[80];
|
||||
time_t statusmsg_time;
|
||||
@ -62,6 +65,10 @@ struct editorConfig {
|
||||
|
||||
struct editorConfig E;
|
||||
|
||||
/*** prototypes ***/
|
||||
|
||||
void editorSetStatusMessage(const char *fmt, ...);
|
||||
|
||||
/*** terminal ***/
|
||||
|
||||
void die(const char *s)
|
||||
@ -311,6 +318,7 @@ void editorAppendRow(char *s, size_t len)
|
||||
editorUpdateRow(&E.row[at]);
|
||||
|
||||
E.numrows++;
|
||||
E.dirty++;
|
||||
}
|
||||
|
||||
void editorRowInsertChar(erow *row, int at, int c)
|
||||
@ -325,6 +333,20 @@ void editorRowInsertChar(erow *row, int at, int c)
|
||||
row->size++;
|
||||
row->chars[at] = c;
|
||||
editorUpdateRow(row);
|
||||
E.dirty++;
|
||||
}
|
||||
|
||||
void editorRowDelChar(erow *row, int at)
|
||||
{
|
||||
if (at < 0 || at >= row->size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memmove(&row->chars[at], &row->chars[at + 1], row->size - at);
|
||||
row->size--;
|
||||
editorUpdateRow(row);
|
||||
E.dirty++;
|
||||
}
|
||||
|
||||
/*** editor operations ***/
|
||||
@ -339,7 +361,46 @@ void editorInsertChar(int c)
|
||||
E.cx++;
|
||||
}
|
||||
|
||||
void editorDelChar()
|
||||
{
|
||||
if (E.cy == E.numrows)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
erow *row = &E.row[E.cy];
|
||||
if (E.cx > 0)
|
||||
{
|
||||
editorRowDelChar(row, E.cx - 1);
|
||||
E.cx--;
|
||||
}
|
||||
}
|
||||
|
||||
/*** file i/o ***/
|
||||
|
||||
char *editorRowsToString(int *buflen)
|
||||
{
|
||||
int totlen = 0;
|
||||
int j;
|
||||
for (j = 0; j < E.numrows; j++)
|
||||
{
|
||||
totlen += E.row[j].size + 1;
|
||||
}
|
||||
*buflen = totlen;
|
||||
|
||||
char *buf = malloc(totlen);
|
||||
char *p = buf;
|
||||
for (j = 0; j < E.numrows; j++)
|
||||
{
|
||||
memcpy(p, E.row[j].chars, E.row[j].size);
|
||||
p += E.row[j].size;
|
||||
*p = '\n';
|
||||
p++;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void editorOpen(char *filename)
|
||||
{
|
||||
free(E.filename);
|
||||
@ -367,6 +428,37 @@ void editorOpen(char *filename)
|
||||
|
||||
free(line);
|
||||
fclose(fp);
|
||||
E.dirty = 0;
|
||||
}
|
||||
|
||||
void editorSave()
|
||||
{
|
||||
if (E.filename == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int len;
|
||||
char *buf = editorRowsToString(&len);
|
||||
|
||||
int fd = open(E.filename, O_RDWR | O_CREAT, 0644);
|
||||
if (fd != -1)
|
||||
{
|
||||
if (ftruncate(fd, len) != -1)
|
||||
{
|
||||
if (write(fd, buf, len) == len)
|
||||
{
|
||||
close(fd);
|
||||
free(buf);
|
||||
E.dirty = 0;
|
||||
editorSetStatusMessage("%d bytes written to disk", len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
free(buf);
|
||||
editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno));
|
||||
}
|
||||
|
||||
/*** append buffer ***/
|
||||
@ -491,8 +583,9 @@ void editorDrawStatusBar(struct abuf *ab)
|
||||
{
|
||||
abAppend(ab, "\x1b[7m", 4);
|
||||
char status[80], rstatus[80];
|
||||
int len = snprintf(status, sizeof(status), "%.20s - %d lines",
|
||||
E.filename ? E.filename : "[No Name]", E.numrows);
|
||||
int len = snprintf(status, sizeof(status), "%.20s - %d lines %s",
|
||||
E.filename ? E.filename : "[No Name]", E.numrows,
|
||||
E.dirty ? "(modified)" : "");
|
||||
int rlen = snprintf(rstatus, sizeof(rstatus), "%d/%d",
|
||||
E.cy + 1, E.numrows);
|
||||
|
||||
@ -626,6 +719,8 @@ void editorMoveCursor(int key)
|
||||
|
||||
void editorProcessKeypress()
|
||||
{
|
||||
static int quit_times = KILO_QUIT_TIMES;
|
||||
|
||||
int c = editorReadKey();
|
||||
|
||||
switch (c)
|
||||
@ -635,11 +730,22 @@ void editorProcessKeypress()
|
||||
break;
|
||||
|
||||
case CTRL_KEY('q'):
|
||||
if (E.dirty && quit_times > 0)
|
||||
{
|
||||
editorSetStatusMessage("WARNING!!! File has unsaved changes ."
|
||||
"Press Ctrl-Q %d more time(s) to quit.", quit_times);
|
||||
quit_times--;
|
||||
return;
|
||||
}
|
||||
write(STDOUT_FILENO, "\x1b[2J", 4);
|
||||
write(STDOUT_FILENO, "\x1b[H", 3);
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
case CTRL_KEY('s'):
|
||||
editorSave();
|
||||
break;
|
||||
|
||||
case HOME_KEY:
|
||||
E.cx = 0;
|
||||
break;
|
||||
@ -654,11 +760,16 @@ void editorProcessKeypress()
|
||||
case BACKSPACE:
|
||||
case CTRL_KEY('h'):
|
||||
case DEL_KEY:
|
||||
/* TODO */
|
||||
if (c == DEL_KEY)
|
||||
{
|
||||
editorMoveCursor(ARROW_RIGHT);
|
||||
}
|
||||
editorDelChar();
|
||||
break;
|
||||
|
||||
case PAGE_UP:
|
||||
case PAGE_DOWN: {
|
||||
case PAGE_DOWN:
|
||||
{
|
||||
if (c == PAGE_UP)
|
||||
{
|
||||
E.cy = E.rowoff;
|
||||
@ -695,6 +806,8 @@ void editorProcessKeypress()
|
||||
editorInsertChar(c);
|
||||
break;
|
||||
}
|
||||
|
||||
quit_times = KILO_QUIT_TIMES;
|
||||
}
|
||||
|
||||
/*** init ***/
|
||||
@ -708,6 +821,7 @@ void initEditor()
|
||||
E.coloff = 0;
|
||||
E.numrows = 0;
|
||||
E.row = NULL;
|
||||
E.dirty = 0;
|
||||
E.filename = NULL;
|
||||
E.statusmsg[0] = '\0';
|
||||
E.statusmsg_time = 0;
|
||||
@ -729,7 +843,7 @@ int main(int argc, char *argv[])
|
||||
editorOpen(argv[1]);
|
||||
}
|
||||
|
||||
editorSetStatusMessage("HELP: Ctrl-Q = quit");
|
||||
editorSetStatusMessage("HELP: Ctrl-S = save | Ctrl-Q = quit");
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user