source: mainline/uspace/app/edit/edit.c@ ba26129

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ba26129 was ba26129, checked in by Jiri Svoboda <jiri@…>, 16 years ago

Prevent overrunning screen width when editing file name.

  • Property mode set to 100644
File size: 17.3 KB
RevLine 
[3052ff4]1/*
2 * Copyright (c) 2009 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup edit
30 * @brief Text editor.
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <stdio.h>
[1352fc1]38#include <stdlib.h>
[3052ff4]39#include <sys/types.h>
40#include <vfs/vfs.h>
41#include <io/console.h>
42#include <io/color.h>
43#include <io/keycode.h>
44#include <errno.h>
45#include <align.h>
46#include <macros.h>
47#include <bool.h>
48
49#include "sheet.h"
50
51enum redraw_flags {
52 REDRAW_TEXT = (1 << 0),
53 REDRAW_ROW = (1 << 1),
54 REDRAW_STATUS = (1 << 2),
55 REDRAW_CARET = (1 << 3)
56};
57
58/** Pane
59 *
60 * A rectangular area of the screen used to edit a document. Different
61 * panes can be possibly used to edit the same document.
62 */
63typedef struct {
64 /* Pane dimensions */
65 int rows, columns;
66
67 /* Position of the visible area */
68 int sh_row, sh_column;
69
70 /** Bitmask of components that need redrawing */
71 enum redraw_flags rflags;
72
73 /** Current position of the caret */
74 tag_t caret_pos;
[743e17b]75
76 /**
77 * Ideal column where the caret should try to get. This is used
78 * for maintaining the same column during vertical movement.
79 */
80 int ideal_column;
[3052ff4]81} pane_t;
82
83/** Document
84 *
85 * Associates a sheet with a file where it can be saved to.
86 */
87typedef struct {
88 char *file_name;
89 sheet_t sh;
90} doc_t;
91
92static int con;
93static doc_t doc;
94static bool done;
95static pane_t pane;
96
[b077886e]97static int scr_rows, scr_columns;
[3052ff4]98
99#define ROW_BUF_SIZE 4096
100#define BUF_SIZE 64
101#define TAB_WIDTH 8
102#define ED_INFTY 65536
103
[ba26129]104/** Maximum filename length that can be entered. */
105#define INFNAME_MAX_LEN 128
106
[3052ff4]107static void key_handle_unmod(console_event_t const *ev);
108static void key_handle_ctrl(console_event_t const *ev);
109static int file_save(char const *fname);
[1352fc1]110static void file_save_as(void);
[3052ff4]111static int file_insert(char *fname);
112static int file_save_range(char const *fname, spt_t const *spos,
113 spt_t const *epos);
[1352fc1]114static char *filename_prompt(char const *prompt, char const *init_value);
[3052ff4]115static void pane_text_display(void);
116static void pane_row_display(void);
117static void pane_row_range_display(int r0, int r1);
118static void pane_status_display(void);
119static void pane_caret_display(void);
120static void insert_char(wchar_t c);
121static void delete_char_before(void);
122static void delete_char_after(void);
123static void caret_update(void);
124static void caret_move(int drow, int dcolumn, enum dir_spec align_dir);
125static void pt_get_sof(spt_t *pt);
126static void pt_get_eof(spt_t *pt);
127static void status_display(char const *str);
128
129
130int main(int argc, char *argv[])
131{
132 console_event_t ev;
133 coord_t coord;
134 bool new_file;
135
136 spt_t pt;
137
138 con = fphone(stdout);
139 console_clear(con);
140
141 console_get_size(con, &scr_columns, &scr_rows);
142
143 pane.rows = scr_rows - 1;
[99e5526]144 pane.columns = scr_columns;
[3052ff4]145 pane.sh_row = 1;
[99e5526]146 pane.sh_column = 1;
[3052ff4]147
148 /* Start with an empty sheet. */
149 sheet_init(&doc.sh);
150
151 /* Place caret at the beginning of file. */
152 coord.row = coord.column = 1;
153 sheet_get_cell_pt(&doc.sh, &coord, dir_before, &pt);
154 sheet_place_tag(&doc.sh, &pt, &pane.caret_pos);
[743e17b]155 pane.ideal_column = coord.column;
[3052ff4]156
157 if (argc == 2) {
[1352fc1]158 doc.file_name = str_dup(argv[1]);
[3052ff4]159 } else if (argc > 1) {
160 printf("Invalid arguments.\n");
161 return -2;
162 } else {
[1352fc1]163 doc.file_name = NULL;
[3052ff4]164 }
165
166 new_file = false;
167
[1352fc1]168 if (doc.file_name == NULL || file_insert(doc.file_name) != EOK)
[3052ff4]169 new_file = true;
170
171 /* Move to beginning of file. */
172 caret_move(-ED_INFTY, -ED_INFTY, dir_before);
173
174 /* Initial display */
175 console_clear(con);
176 pane_text_display();
177 pane_status_display();
[1352fc1]178 if (new_file && doc.file_name != NULL)
179 status_display("File not found. Starting empty file.");
[3052ff4]180 pane_caret_display();
181
182
183 done = false;
184
185 while (!done) {
186 console_get_event(con, &ev);
187 pane.rflags = 0;
188
189 if (ev.type == KEY_PRESS) {
190 /* Handle key press. */
191 if (((ev.mods & KM_ALT) == 0) &&
192 (ev.mods & KM_CTRL) != 0) {
193 key_handle_ctrl(&ev);
194 } else if ((ev.mods & (KM_CTRL | KM_ALT)) == 0) {
195 key_handle_unmod(&ev);
196 }
197 }
198
199 /* Redraw as necessary. */
200
201 if (pane.rflags & REDRAW_TEXT)
202 pane_text_display();
203 if (pane.rflags & REDRAW_ROW)
204 pane_row_display();
205 if (pane.rflags & REDRAW_STATUS)
206 pane_status_display();
207 if (pane.rflags & REDRAW_CARET)
208 pane_caret_display();
209
210 }
211
212 console_clear(con);
213
214 return 0;
215}
216
217/** Handle key without modifier. */
218static void key_handle_unmod(console_event_t const *ev)
219{
220 switch (ev->key) {
221 case KC_ENTER:
222 insert_char('\n');
223 caret_update();
224 break;
225 case KC_LEFT:
226 caret_move(0, -1, dir_before);
227 break;
228 case KC_RIGHT:
229 caret_move(0, 0, dir_after);
230 break;
231 case KC_UP:
232 caret_move(-1, 0, dir_before);
233 break;
234 case KC_DOWN:
235 caret_move(+1, 0, dir_before);
236 break;
237 case KC_HOME:
238 caret_move(0, -ED_INFTY, dir_before);
239 break;
240 case KC_END:
241 caret_move(0, +ED_INFTY, dir_before);
242 break;
243 case KC_PAGE_UP:
244 caret_move(-pane.rows, 0, dir_before);
245 break;
246 case KC_PAGE_DOWN:
247 caret_move(+pane.rows, 0, dir_before);
248 break;
249 case KC_BACKSPACE:
250 delete_char_before();
251 caret_update();
252 break;
253 case KC_DELETE:
254 delete_char_after();
255 caret_update();
256 break;
257 default:
258 if (ev->c >= 32 || ev->c == '\t') {
259 insert_char(ev->c);
260 caret_update();
261 }
262 break;
263 }
264}
265
266/** Handle Ctrl-key combination. */
267static void key_handle_ctrl(console_event_t const *ev)
268{
269 switch (ev->key) {
270 case KC_Q:
271 done = true;
272 break;
273 case KC_S:
[1352fc1]274 if (doc.file_name != NULL)
275 file_save(doc.file_name);
276 else
277 file_save_as();
278 break;
279 case KC_E:
280 file_save_as();
[3052ff4]281 break;
282 default:
283 break;
284 }
285}
286
287/** Save the document. */
288static int file_save(char const *fname)
289{
290 spt_t sp, ep;
291 int rc;
292
293 status_display("Saving...");
294 pt_get_sof(&sp);
295 pt_get_eof(&ep);
296
297 rc = file_save_range(fname, &sp, &ep);
[1352fc1]298
299 switch (rc) {
300 case EINVAL:
301 status_display("Error opening file!");
302 break;
303 case EIO:
304 status_display("Error writing data!");
305 break;
306 default:
307 status_display("File saved.");
308 break;
309 }
[3052ff4]310
311 return rc;
312}
313
[1352fc1]314/** Change document name and save. */
315static void file_save_as(void)
316{
317 char *old_fname, *fname;
318 int rc;
319
320 old_fname = (doc.file_name != NULL) ? doc.file_name : "";
321 fname = filename_prompt("Save As", old_fname);
322 if (fname == NULL) {
323 status_display("Save cancelled.");
324 return;
325 }
326
327 rc = file_save(fname);
328 if (rc != EOK)
329 return;
330
331 if (doc.file_name != NULL)
332 free(doc.file_name);
333 doc.file_name = fname;
334}
335
336/** Ask for a file name. */
337static char *filename_prompt(char const *prompt, char const *init_value)
338{
339 console_event_t ev;
340 char *str;
[ba26129]341 wchar_t buffer[INFNAME_MAX_LEN + 1];
342 int max_len;
[1352fc1]343 int nc;
344 bool done;
345
346 asprintf(&str, "%s: %s", prompt, init_value);
347 status_display(str);
348 console_goto(con, 1 + str_length(str), scr_rows - 1);
349 free(str);
350
351 console_set_color(con, COLOR_WHITE, COLOR_BLACK, 0);
352
[ba26129]353 max_len = min(INFNAME_MAX_LEN, scr_columns - 4 - str_length(prompt));
354 str_to_wstr(buffer, max_len + 1, init_value);
[1352fc1]355 nc = wstr_length(buffer);
356 done = false;
357
358 while (!done) {
359 console_get_event(con, &ev);
360
361 if (ev.type == KEY_PRESS) {
362 /* Handle key press. */
363 if (((ev.mods & KM_ALT) == 0) &&
364 (ev.mods & KM_CTRL) != 0) {
365 ;
366 } else if ((ev.mods & (KM_CTRL | KM_ALT)) == 0) {
367 switch (ev.key) {
368 case KC_ESCAPE:
369 return NULL;
370 case KC_BACKSPACE:
371 if (nc > 0) {
372 putchar('\b');
373 fflush(stdout);
374 --nc;
375 }
376 break;
377 case KC_ENTER:
378 done = true;
379 break;
380 default:
[ba26129]381 if (ev.c >= 32 && nc < max_len) {
[1352fc1]382 putchar(ev.c);
383 fflush(stdout);
384 buffer[nc++] = ev.c;
385 }
386 break;
387 }
388 }
389 }
390 }
391
392 buffer[nc] = '\0';
393
394 str = malloc(STR_BOUNDS(wstr_length(buffer)) + 1);
395 if (str == NULL)
396 return NULL;
397
398 wstr_nstr(str, buffer, STR_BOUNDS(wstr_length(buffer)) + 1);
399
400 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0);
401
402 return str;
403}
404
[3052ff4]405/** Insert file at caret position.
406 *
407 * Reads in the contents of a file and inserts them at the current position
408 * of the caret.
409 */
410static int file_insert(char *fname)
411{
412 FILE *f;
413 wchar_t c;
414 char buf[BUF_SIZE];
415 int bcnt;
416 int n_read;
417 size_t off;
418
419 f = fopen(fname, "rt");
420 if (f == NULL)
421 return EINVAL;
422
423 bcnt = 0;
424
425 while (true) {
426 if (bcnt < STR_BOUNDS(1)) {
427 n_read = fread(buf + bcnt, 1, BUF_SIZE - bcnt, f);
428 bcnt += n_read;
429 }
430
431 off = 0;
432 c = str_decode(buf, &off, bcnt);
433 if (c == '\0')
434 break;
435
436 bcnt -= off;
437 memcpy(buf, buf + off, bcnt);
438
439 insert_char(c);
440 }
441
442 fclose(f);
443
444 return EOK;
445}
446
447/** Save a range of text into a file. */
448static int file_save_range(char const *fname, spt_t const *spos,
449 spt_t const *epos)
450{
451 FILE *f;
452 char buf[BUF_SIZE];
453 spt_t sp, bep;
454 size_t bytes, n_written;
455
456 f = fopen(fname, "wt");
457 if (f == NULL)
458 return EINVAL;
459
460 sp = *spos;
461
462 do {
463 sheet_copy_out(&doc.sh, &sp, epos, buf, BUF_SIZE, &bep);
464 bytes = str_size(buf);
465
466 n_written = fwrite(buf, 1, bytes, f);
467 if (n_written != bytes) {
468 return EIO;
469 }
470
471 sp = bep;
472 } while (!spt_equal(&bep, epos));
473
[1352fc1]474 if (fclose(f) != EOK)
475 return EIO;
[3052ff4]476
477 return EOK;
478}
479
480static void pane_text_display(void)
481{
482 int sh_rows, rows;
[b077886e]483 int i, j;
[3052ff4]484
485 sheet_get_num_rows(&doc.sh, &sh_rows);
486 rows = min(sh_rows - pane.sh_row + 1, pane.rows);
487
488 /* Draw rows from the sheet. */
489
490 console_goto(con, 0, 0);
491 pane_row_range_display(0, rows);
492
493 /* Clear the remaining rows if file is short. */
494
495 for (i = rows; i < pane.rows; ++i) {
496 console_goto(con, 0, i);
497 for (j = 0; j < scr_columns; ++j)
498 putchar(' ');
499 fflush(stdout);
500 }
501
502 pane.rflags |= (REDRAW_STATUS | REDRAW_CARET);
503 pane.rflags &= ~REDRAW_ROW;
504}
505
506/** Display just the row where the caret is. */
507static void pane_row_display(void)
508{
509 spt_t caret_pt;
510 coord_t coord;
511 int ridx;
512
513 tag_get_pt(&pane.caret_pos, &caret_pt);
514 spt_get_coord(&caret_pt, &coord);
515
516 ridx = coord.row - pane.sh_row;
517 pane_row_range_display(ridx, ridx + 1);
518 pane.rflags |= (REDRAW_STATUS | REDRAW_CARET);
519}
520
521static void pane_row_range_display(int r0, int r1)
522{
523 int i, j, fill;
524 spt_t rb, re, dep;
525 coord_t rbc, rec;
526 char row_buf[ROW_BUF_SIZE];
527 wchar_t c;
528 size_t pos, size;
529 unsigned s_column;
530
531 /* Draw rows from the sheet. */
532
533 console_goto(con, 0, 0);
534 for (i = r0; i < r1; ++i) {
[99e5526]535 /* Starting point for row display */
536 rbc.row = pane.sh_row + i;
537 rbc.column = pane.sh_column;
[3052ff4]538 sheet_get_cell_pt(&doc.sh, &rbc, dir_before, &rb);
539
[99e5526]540 /* Ending point for row display */
541 rec.row = pane.sh_row + i;
542 rec.column = pane.sh_column + pane.columns;
[3052ff4]543 sheet_get_cell_pt(&doc.sh, &rec, dir_before, &re);
544
545 /* Copy the text of the row to the buffer. */
546 sheet_copy_out(&doc.sh, &rb, &re, row_buf, ROW_BUF_SIZE, &dep);
547
548 /* Display text from the buffer. */
549
550 console_goto(con, 0, i);
551 size = str_size(row_buf);
552 pos = 0;
553 s_column = 1;
554 while (pos < size) {
555 c = str_decode(row_buf, &pos, size);
556 if (c != '\t') {
557 printf("%lc", c);
558 s_column += 1;
559 } else {
560 fill = 1 + ALIGN_UP(s_column, TAB_WIDTH)
561 - s_column;
562
563 for (j = 0; j < fill; ++j)
564 putchar(' ');
565 s_column += fill;
566 }
567 }
568
569 /* Fill until the end of display area. */
570
[b077886e]571 if (str_length(row_buf) < (unsigned) scr_columns)
[3052ff4]572 fill = scr_columns - str_length(row_buf);
573 else
574 fill = 0;
575
576 for (j = 0; j < fill; ++j)
577 putchar(' ');
578 fflush(stdout);
579 }
580
581 pane.rflags |= REDRAW_CARET;
582}
583
584/** Display pane status in the status line. */
585static void pane_status_display(void)
586{
587 spt_t caret_pt;
588 coord_t coord;
[1352fc1]589 char *fname;
[3052ff4]590 int n;
591
592 tag_get_pt(&pane.caret_pos, &caret_pt);
593 spt_get_coord(&caret_pt, &coord);
594
[1352fc1]595 fname = (doc.file_name != NULL) ? doc.file_name : "<unnamed>";
596
[3052ff4]597 console_goto(con, 0, scr_rows - 1);
598 console_set_color(con, COLOR_WHITE, COLOR_BLACK, 0);
[1352fc1]599 n = printf(" %d, %d: File '%s'. Ctrl-Q Quit Ctrl-S Save "
600 "Ctrl-E Save As", coord.row, coord.column, fname);
[3052ff4]601 printf("%*s", scr_columns - 1 - n, "");
602 fflush(stdout);
603 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0);
604
605 pane.rflags |= REDRAW_CARET;
606}
607
608/** Set cursor to reflect position of the caret. */
609static void pane_caret_display(void)
610{
611 spt_t caret_pt;
612 coord_t coord;
613
614 tag_get_pt(&pane.caret_pos, &caret_pt);
615
616 spt_get_coord(&caret_pt, &coord);
[99e5526]617 console_goto(con, coord.column - pane.sh_column,
618 coord.row - pane.sh_row);
[3052ff4]619}
620
621/** Insert a character at caret position. */
622static void insert_char(wchar_t c)
623{
624 spt_t pt;
625 char cbuf[STR_BOUNDS(1) + 1];
626 size_t offs;
627
628 tag_get_pt(&pane.caret_pos, &pt);
629
630 offs = 0;
631 chr_encode(c, cbuf, &offs, STR_BOUNDS(1) + 1);
632 cbuf[offs] = '\0';
633
634 (void) sheet_insert(&doc.sh, &pt, dir_before, cbuf);
[884b461]635
636 pane.rflags |= REDRAW_ROW;
637 if (c == '\n')
638 pane.rflags |= REDRAW_TEXT;
[3052ff4]639}
640
641/** Delete the character before the caret. */
642static void delete_char_before(void)
643{
644 spt_t sp, ep;
645 coord_t coord;
646
647 tag_get_pt(&pane.caret_pos, &ep);
648 spt_get_coord(&ep, &coord);
649
650 coord.column -= 1;
651 sheet_get_cell_pt(&doc.sh, &coord, dir_before, &sp);
652
653 (void) sheet_delete(&doc.sh, &sp, &ep);
[884b461]654
655 pane.rflags |= REDRAW_ROW;
656 if (coord.column < 1)
657 pane.rflags |= REDRAW_TEXT;
[3052ff4]658}
659
660/** Delete the character after the caret. */
661static void delete_char_after(void)
662{
663 spt_t sp, ep;
[884b461]664 coord_t sc, ec;
[3052ff4]665
666 tag_get_pt(&pane.caret_pos, &sp);
[884b461]667 spt_get_coord(&sp, &sc);
[3052ff4]668
[884b461]669 sheet_get_cell_pt(&doc.sh, &sc, dir_after, &ep);
670 spt_get_coord(&ep, &ec);
[3052ff4]671
672 (void) sheet_delete(&doc.sh, &sp, &ep);
[884b461]673
674 pane.rflags |= REDRAW_ROW;
675 if (ec.row != sc.row)
676 pane.rflags |= REDRAW_TEXT;
[3052ff4]677}
678
679/** Scroll pane after caret has moved.
680 *
681 * After modifying the position of the caret, this is called to scroll
682 * the pane to ensure that the caret is in the visible area.
683 */
684static void caret_update(void)
685{
686 spt_t pt;
687 coord_t coord;
688
689 tag_get_pt(&pane.caret_pos, &pt);
690 spt_get_coord(&pt, &coord);
691
[99e5526]692 /* Scroll pane vertically. */
[3052ff4]693
694 if (coord.row < pane.sh_row) {
695 pane.sh_row = coord.row;
696 pane.rflags |= REDRAW_TEXT;
697 }
[99e5526]698
[3052ff4]699 if (coord.row > pane.sh_row + pane.rows - 1) {
700 pane.sh_row = coord.row - pane.rows + 1;
701 pane.rflags |= REDRAW_TEXT;
702 }
703
[99e5526]704 /* Scroll pane horizontally. */
705
706 if (coord.column < pane.sh_column) {
707 pane.sh_column = coord.column;
708 pane.rflags |= REDRAW_TEXT;
709 }
[3052ff4]710
[99e5526]711 if (coord.column > pane.sh_column + pane.columns - 1) {
712 pane.sh_column = coord.column - pane.columns + 1;
713 pane.rflags |= REDRAW_TEXT;
714 }
715
716 pane.rflags |= (REDRAW_CARET | REDRAW_STATUS);
[3052ff4]717}
718
719/** Change the caret position.
720 *
721 * Moves caret relatively to the current position. Looking at the first
722 * character cell after the caret and moving by @a drow and @a dcolumn, we get
723 * to a new character cell, and thus a new character. Then we either go to the
724 * point before the the character or after it, depending on @a align_dir.
725 */
726static void caret_move(int drow, int dcolumn, enum dir_spec align_dir)
727{
728 spt_t pt;
729 coord_t coord;
730 int num_rows;
[743e17b]731 bool pure_vertical;
[3052ff4]732
733 tag_get_pt(&pane.caret_pos, &pt);
734 spt_get_coord(&pt, &coord);
735 coord.row += drow; coord.column += dcolumn;
736
737 /* Clamp coordinates. */
738 if (drow < 0 && coord.row < 1) coord.row = 1;
739 if (dcolumn < 0 && coord.column < 1) coord.column = 1;
740 if (drow > 0) {
741 sheet_get_num_rows(&doc.sh, &num_rows);
742 if (coord.row > num_rows) coord.row = num_rows;
743 }
744
[743e17b]745 /* For purely vertical movement try attaining @c ideal_column. */
746 pure_vertical = (dcolumn == 0 && align_dir == dir_before);
747 if (pure_vertical)
748 coord.column = pane.ideal_column;
749
[3052ff4]750 /*
751 * Select the point before or after the character at the designated
752 * coordinates. The character can be wider than one cell (e.g. tab).
753 */
754 sheet_get_cell_pt(&doc.sh, &coord, align_dir, &pt);
755 sheet_remove_tag(&doc.sh, &pane.caret_pos);
756 sheet_place_tag(&doc.sh, &pt, &pane.caret_pos);
757
[743e17b]758 /* For non-vertical movement set the new value for @c ideal_column. */
759 if (!pure_vertical) {
760 spt_get_coord(&pt, &coord);
761 pane.ideal_column = coord.column;
762 }
763
[3052ff4]764 caret_update();
765}
766
767
768/** Get start-of-file s-point. */
769static void pt_get_sof(spt_t *pt)
770{
771 coord_t coord;
772
773 coord.row = coord.column = 1;
774 sheet_get_cell_pt(&doc.sh, &coord, dir_before, pt);
775}
776
777/** Get end-of-file s-point. */
778static void pt_get_eof(spt_t *pt)
779{
780 coord_t coord;
781 int num_rows;
782
783 sheet_get_num_rows(&doc.sh, &num_rows);
[00413c5c]784 coord.row = num_rows + 1;
[3052ff4]785 coord.column = 1;
786
787 sheet_get_cell_pt(&doc.sh, &coord, dir_after, pt);
788}
789
790/** Display text in the status line. */
791static void status_display(char const *str)
792{
793 console_goto(con, 0, scr_rows - 1);
794 console_set_color(con, COLOR_WHITE, COLOR_BLACK, 0);
795 printf(" %*s ", -(scr_columns - 3), str);
796 fflush(stdout);
797 console_set_color(con, COLOR_BLACK, COLOR_WHITE, 0);
798
799 pane.rflags |= REDRAW_CARET;
800}
801
802/** @}
803 */
Note: See TracBrowser for help on using the repository browser.