2 * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
4 * See file CREDITS for list of people who contributed to this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * @brief A tiny editor implementation
30 #include <linux/ctype.h>
35 #include <linux/stat.h>
46 static struct line
*buffer
;
48 static struct line
*lastscrline
;
50 static int screenwidth
= 80;
51 static int screenheight
= 25;
53 static int cursx
= 0; /* position on screen */
56 static int textx
= 0; /* position in text */
58 static struct line
*curline
; /* line where the cursor is */
60 static struct line
*scrline
; /* the first line on screen */
61 int scrcol
= 0; /* the first column on screen */
63 static void pos(int x
, int y
)
65 printf("%c[%d;%dH", 27, y
+ 1, x
+ 1);
68 static char *screenline(char *line
, int *pos
)
71 static char lbuf
[1024];
73 memset(lbuf
, 0, 1024);
80 for (i
= 0; outpos
< 1024; i
++) {
81 if (i
== textx
&& pos
)
85 if (line
[i
] == '\t') {
87 while (outpos
% TABSPACE
)
91 lbuf
[outpos
++] = line
[i
];
97 static int setpos(char *line
, int position
)
102 while(line
[linepos
]) {
103 if (line
[linepos
] == '\t')
104 while ((i
+ 1) % TABSPACE
)
115 static void refresh_line(struct line
*line
, int ypos
)
117 char *str
= screenline(line
->data
, NULL
) + scrcol
;
119 str
[screenwidth
] = 0;
120 printf("%s%c[K", str
, 27);
125 * Most sane terminal programs can do ansi screen scrolling.
126 * Unfortunately one of the most popular programs cannot:
130 static int smartscroll
= 0;
132 static void refresh(int full
)
135 struct line
*l
= scrline
;
139 if (scrline
->next
== lastscrline
) {
141 refresh_line(scrline
, 0);
142 pos(0, screenheight
);
143 printf("%*s", screenwidth
, "");
147 if (scrline
->prev
== lastscrline
) {
149 for (i
= 0; i
< screenheight
- 1; i
++) {
154 refresh_line(l
, screenheight
- 1);
163 for (i
= 0; i
< screenheight
; i
++) {
171 while (i
< screenheight
) {
177 static void line_free(struct line
*line
)
183 static struct line
*line_realloc(int len
, struct line
*line
)
188 line
= xzalloc(sizeof(struct line
));
189 line
->data
= malloc(32);
195 line
->data
= xrealloc(line
->data
, size
);
199 static int edit_read_file(const char *path
)
202 struct line
*lastline
= NULL
;
204 char *linestr
, *lineend
;
207 if (!stat(path
, &s
)) {
208 filebuffer
= read_file(path
, NULL
);
210 printf("could not read %s: %s\n", path
, errno_str());
214 linestr
= filebuffer
;
219 lineend
= strchr(linestr
, '\n');
221 if (!lineend
&& !*linestr
)
227 line
= line_realloc(strlen(linestr
) + 1, NULL
);
230 memcpy(line
->data
, linestr
, strlen(linestr
) + 1);
231 line
->prev
= lastline
;
233 lastline
->next
= line
;
240 linestr
= lineend
+ 1;
246 buffer
= line_realloc(0, NULL
);
253 static void free_buffer(void)
255 struct line
*line
, *tmp
;
266 static int save_file(const char *path
)
268 struct line
*line
, *tmp
;
271 fd
= open(path
, O_WRONLY
| O_TRUNC
| O_CREAT
);
273 printf("could not open file for writing: %s\n", errno_str());
281 write(fd
, line
->data
, strlen(line
->data
));
289 static void insert_char(char c
)
293 int end
= strlen(curline
->data
);
295 line_realloc(strlen(curline
->data
) + 2, curline
);
296 line
= curline
->data
;
299 line
[end
+ 1] = line
[end
];
304 refresh_line(curline
, cursy
);
307 static void delete_char(int pos
)
309 char *line
= curline
->data
;
310 int end
= strlen(line
);
313 line
[pos
] = line
[pos
+ 1];
316 refresh_line(curline
, cursy
);
319 static void split_line(void)
321 int length
= strlen(curline
->data
+ textx
);
322 struct line
*newline
= line_realloc(length
+ 1, NULL
);
325 memcpy(newline
->data
, curline
->data
+ textx
, length
+ 1);
327 curline
->data
[textx
] = 0;
330 curline
->next
= newline
;
331 newline
->prev
= curline
;
338 curline
= curline
->next
;
342 static void merge_line(struct line
*line
)
346 line_realloc(strlen(line
->data
) + strlen(line
->next
->data
) + 1, line
);
350 line
->next
= line
->next
->next
;
352 line
->next
->prev
= line
;
353 strcat(line
->data
, tmp
->data
);
360 /* not a good idea on slow serial lines */
361 /* #define GETWINSIZE */
364 static void getwinsize(void) {
365 int y
, yy
= 25, xx
= 80, i
, n
, r
;
369 for (y
= 25; y
< 320; y
++) {
373 while ((r
= getc()) != 'R') {
377 n
= simple_strtoul(buf
+ 2, &endp
, 10);
380 n
= simple_strtoul(endp
+ 1, NULL
, 10);
387 printf("%d %d\n", xx
, yy
);
392 static int do_edit(cmd_tbl_t
* cmdtp
, int argc
, char *argv
[])
400 return COMMAND_ERROR_USAGE
;
402 /* check if we are called as "sedit" insted of "edit" */
407 if(edit_read_file(argv
[1]))
420 lastscrline
= scrline
;
427 int curlen
= strlen(curline
->data
);
434 screenline(curline
->data
, &linepos
);
436 if (linepos
> scrcol
+ screenwidth
)
437 scrcol
= linepos
- screenwidth
;
439 if (scrcol
> linepos
)
442 cursx
= linepos
- scrcol
;
444 while (cursy
>= screenheight
) {
446 scrline
= scrline
->next
;
451 scrline
= scrline
->prev
;
454 if (scrline
!= lastscrline
|| scrcol
!= lastscrcol
)
458 lastscrline
= scrline
;
467 curline
= curline
->prev
;
469 textx
= setpos(curline
->data
, linepos
);
475 curline
= curline
->next
;
477 textx
= setpos(curline
->data
, linepos
);
492 for (i
= 0; i
< screenheight
- 1; i
++) {
496 curline
= curline
->prev
;
498 textx
= setpos(curline
->data
, linepos
);
501 for (i
= 0; i
< screenheight
- 1; i
++) {
505 curline
= curline
->next
;
507 textx
= setpos(curline
->data
, linepos
);
510 if (textx
== curlen
) {
528 curline
= curline
->prev
;
530 textx
= strlen(curline
->data
);
540 if ((signed char)c
!= -1)
551 static const char *edit_aliases
[] = { "sedit", NULL
};
553 static const __maybe_unused
char cmd_edit_help
[] =
554 "Usage: (s)edit <file>\n"
555 "This is a very small editor. Its only features are moving the cursor with\n"
556 "the usual keys and typing characters.\n"
557 "<ctrl-c> quits the editor without saving,\n"
558 "<ctrl-d> quits the editor with saving the current file.\n"
560 "If called as sedit the editor uses ansi codes to scroll the screen.\n";
562 static const __maybe_unused
char cmd_edit_usage
[] = "edit a file";
564 U_BOOT_CMD_START(edit
)
566 .aliases
= edit_aliases
,
567 .usage
= cmd_edit_usage
,
568 U_BOOT_CMD_HELP(cmd_edit_help
)
573 * @page edit_command edit (editor)
575 * Usage is: [s]edit \<file\>
577 * This is a very small editor. It's only features are moving the cursor with
578 * the usual keys and typing characters.
580 * \b \<ctrl-c\> quits the editor without saving,\n
581 * \b \<ctrl-d\> quits the editor with saving the current file.
583 * If called as \c sedit the editor uses ansi codes to scroll the screen.