📄 sted.c
字号:
/*************************************************************************** * sted 0.01 - Simple (and/or Stupid) Text Editor, by Linus Akerlund. * e-mail: uxm165t@tninet.se * homepage: http://user.tninet.se/~uxm165t/index.htm * * (C) 1998 Linus Akerlund * * sted is a little program that lets you edit text files. It's supposed * to be small and simple. The code is also simple, but as I'm not very * much of a programmer, it may not be as small as it should be. You'll * find lots of strange things if you take a look at the code, because I'm * not very good at this (yet?). If you find something that could have been * done in a better (more economical, more efficient) way, please send me * an e-mail and tell me about it, or just fix it and send me a patch. I've * seen quite a few things in the code that I can improve a lot, and I'll * probably get around to doing something about that, before I start * implementing functions that makes this resemble a real text editor. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * **************************************************************************/#include <curses.h>#include <signal.h>#include <string.h>#include <stdlib.h>#define LINE_LENGTH 255 /* Maximum length of a line. */#define TAB_SPACING 5 /* Number of characters per tab. */struct line { /* The storage for the text. */ char *content; int number; struct line *next; };typedef struct line rad; /* And a typedef, because I'm to lazy to type * 'struct' all the time. */static void finish (int sig);void clean_up (void);void push_numbers (int line_number);void add_line (char *buffer, int line_number);void modify_line (char *buffer, int line_number);void del_line (int line_number);char *get_line (int line_number);void show_list (int top_line, int left_col, int y, int x);int save_file (char *file_name);int load_file (char *file_name, int *lines);rad *head = NULL; /* The head pointer for the linked list. *//************************************************************************** * The main function * Returns: nothing (will change). * Arguments: the usual ones. * * Does some initializations and then starts waiting for input from the * user. Processes the input and stores it. **************************************************************************/voidmain (int argc, char *argv[]){ int count = 0, count2 = 0, count3 = 0, c, x = 0, y = 0; int line_number = 0, x_pos = 0, lines = 0, *lines_p = &lines; int top_line = 0, left_col = 0; int save_err = 0, load_err = 0, colour = 2, colour_on = 0; char buffer[LINE_LENGTH + 1], temp_buffer[LINE_LENGTH + 1]; char file_name[257]; for (count = 0; count < LINE_LENGTH; count++) temp_buffer[count] = buffer[count] = '\0'; for (count = 0; count < 256; count++) file_name[count] = '\0'; (void) signal (SIGINT, finish); /* arrange interrupts to terminate */ (void) initscr (); /* initialize the curses library */ keypad (stdscr, TRUE); /* enable keyboard mapping */ (void) cbreak (); /* take input chars one at a time, no wait for NL */ (void) noecho (); /* don't echo input */ refresh (); /* to clear the screen */ if (has_colors ()) { start_color (); /* * simple colour assigment, often all we need. * This comes straight from the ncurses tutorial... * No colours are used in this program. */ init_pair (COLOR_BLACK, COLOR_BLACK, COLOR_BLACK); init_pair (COLOR_GREEN, COLOR_GREEN, COLOR_BLACK); init_pair (COLOR_RED, COLOR_RED, COLOR_BLACK); init_pair (COLOR_CYAN, COLOR_CYAN, COLOR_BLACK); init_pair (COLOR_WHITE, COLOR_WHITE, COLOR_BLACK); init_pair (COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK); init_pair (COLOR_BLUE, COLOR_BLUE, COLOR_BLACK); init_pair (COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK); } if (argc > 1) { for (count2 = 1; count2 < argc; count2++) { if (argv[count2][0] == '-') { if (argv[count2][1] == 'p') colour_on = 1; count = 1; } else { strcpy (file_name, argv[count2]); load_err = load_file (file_name, lines_p); if (load_err != 0) { move (12, 0); clrtoeol (); addstr ("Could not open file "); for (count = 0; count < (strlen (file_name)); count++) addch (file_name[count]); addstr (". Starting with empty buffer."); refresh (); getch (); } else strcpy (buffer, get_line (0)); } show_list (top_line, left_col, y, x); refresh (); move (0, 0); } }/* This is the main loop, which lets you input characters, and processes * them in a more or less appropriate way. */ while (1) { c = getch (); /* accept single key as input */ getsyx (y, x); /* Get cursor coordinates */ switch (c) { case 1 ... 8 : case 11 ... 30 : case 32 ... 153 : /* Most characters... */ if (strlen (buffer) == LINE_LENGTH - 1) break; /* Removed all the beeps. */ else { for (count = strlen (buffer) + 1; count > x_pos; count--) buffer[count] = buffer[count - 1]; buffer[x_pos++] = c; if (x == COLS - 1) { ++left_col; } move (y, x_pos - left_col); } break; case '\t' : if (strlen(buffer) == (LINE_LENGTH - 1)) break; else { for (count = strlen (buffer) + 1; count > x_pos; count--) buffer[count] = buffer[count - 1]; buffer[x_pos++] = '\t'; for (count3 = 0; count3 < (TAB_SPACING - 1); count3++) { for (count2 = strlen (buffer) +1; count2 > x_pos; count2--) buffer[count2] = buffer[count2 - 1]; buffer[x_pos++] = ' '; if (left_col < (x_pos - COLS)) left_col = x_pos - COLS; move (y, x_pos - left_col); if (((x_pos + count2) % TAB_SPACING) == 0) break; } } break; case '\n': /* It's ugly, isn't it? Enter... */ for (count = x_pos; count < strlen (buffer); count++) temp_buffer[count - x_pos] = buffer[count]; buffer[x_pos] = '\0'; move (y, 0); push_numbers (line_number); add_line (buffer, line_number); for (count = 0; count < LINE_LENGTH; count++) { buffer[count] = temp_buffer[count]; temp_buffer[count] = '\0'; } if (y == LINES - 1) { ++top_line; move (y, 0); } else move (++y, 0); left_col = 0; ++line_number; ++lines; x_pos = 0; move(y, x_pos - left_col); break; case KEY_BACKSPACE: /* Backspace is not delete */ if (x_pos == 0 && line_number == 0) break; /* Removed all the beeps */ else if (x_pos == 0) { strcpy (temp_buffer, get_line (line_number - 1)); if (strlen (temp_buffer) + strlen (buffer) < LINE_LENGTH) { if (lines > line_number) { del_line (line_number); --lines; } --line_number; x_pos = strlen (temp_buffer); left_col = x_pos - COLS - 1; if (left_col < 0) left_col = 0; strcat (temp_buffer, buffer); strcpy (buffer, temp_buffer); if (y == 0) { --top_line; move (y, 0); } else move (--y, 0); move (y, x_pos - left_col); for (count = 0; count < LINE_LENGTH; count++) temp_buffer[count] = '\0'; } else break; /* Removed all the beeps. */ } else { for (count = x_pos - 1; count < strlen (buffer); count++) buffer[count] = buffer[count + 1]; buffer[strlen (buffer) + 1] = '\0'; --x_pos; if (x == 0) --left_col; move (y, x_pos - left_col); } break; case KEY_DC: /* Delete key, the way I want it to work */ if (x_pos == strlen (buffer)) { if (line_number >= lines - 1) break; /* Removed all the beeps. */ else { strcpy (temp_buffer, get_line (line_number + 1)); if (strlen (temp_buffer) + strlen (buffer) < LINE_LENGTH) { del_line (line_number + 1); --lines; strcat (buffer, temp_buffer); move (y, x_pos - left_col); for (count = 0; count < LINE_LENGTH; count++) temp_buffer[count] = '\0'; } else break; /* Removed all the beeps. */ } } else { for (count = x_pos; count < strlen (buffer); count++) buffer[count] = buffer[count + 1]; buffer[strlen (buffer) + 1] = '\0'; move (y, x_pos - left_col); } break; case KEY_LEFT: /* Cursor left. */ if (x == 0) { if ((line_number == 0) && (left_col == 0)) break; /* Removed all the beeps. */ else if (left_col > 0) { --left_col; --x_pos; } else { if (line_number == lines) { add_line (buffer, line_number); ++lines; } else modify_line (buffer, line_number); strcpy (buffer, get_line (--line_number)); if (buffer == NULL) { fprintf (stderr, "Couldn't get any line!"); exit (1); } if (y == 0) { --top_line; move (y, 0); } else move (--y, 0); x_pos = strlen (buffer); left_col = x_pos - (COLS - 1); if (left_col < 0) left_col = 0; move (y, x_pos - left_col); } } else move (y, (--x_pos) - left_col); break; case KEY_RIGHT: /* Cursor right. */ if (x_pos == strlen(buffer)) { if (line_number >= lines - 1) break; /* Removed all the beeps. */ else { modify_line (buffer, line_number); strcpy (buffer, get_line (++line_number)); if (buffer == NULL) { fprintf (stderr, "Couldn't get any line!"); exit (1); } if (y == LINES - 1) { ++top_line; move (y, 0); } else move (++y, 0); x_pos = 0; left_col = 0; move (y, x_pos - left_col); } } else if (x == (COLS - 1)) { ++x_pos; ++left_col; move(y, x_pos - left_col); } else move (y, (++x_pos) - left_col); break; case KEY_HOME: /* Home: to beginning of line. */ x_pos = 0; left_col = 0; break; case KEY_END: /* End: to end of line. */ x_pos = strlen(buffer); if ((x_pos) > (left_col + (COLS - 1))) left_col = x_pos - (COLS - 1); break; case KEY_UP: /* Cursor up. */ if (line_number == 0) break; /* Removed all the beeps. */ else { if (line_number == lines) { add_line (buffer, line_number); ++lines; } else modify_line (buffer, line_number); strcpy (buffer, get_line (--line_number)); if (buffer == NULL) { fprintf (stderr, "Couldn't get any line!"); exit (1); } if (y == 0) { --top_line; move (y, 0); } else move (--y, 0); if (x_pos > strlen (buffer)) x_pos = strlen (buffer); if (x_pos < left_col) left_col = x_pos; move (y, x_pos - left_col); } show_list (top_line, left_col, y, x); break; case KEY_DOWN: /* Cursor down. */ if (line_number >= lines - 1) break; /* Removed all the beeps. */ else { modify_line (buffer, line_number); strcpy (buffer, get_line (++line_number)); if (buffer == NULL) { fprintf (stderr, "Couldn't get any line!"); exit (1); } if (y == LINES - 1) { ++top_line; move (y, 0); } else move (++y, 0); if (x_pos > strlen (buffer)) x_pos = strlen (buffer); if (x_pos < left_col) left_col = x_pos; move (y, x_pos - left_col); } show_list (top_line, left_col, y, x); break; case (KEY_NPAGE): if (line_number >= lines - 1) break; /* Removed all the beeps. */ else { modify_line (buffer, line_number); if (y == LINES - 1) { line_number += (LINES - 1); if (line_number >= lines) line_number = lines - 1; top_line = line_number - (LINES - 1); y = lines - top_line - 1; } else { y = LINES - 1; line_number = top_line + (LINES - 1); if (line_number >= lines) { line_number = lines - 1; y = lines - top_line - 1; } } strcpy (buffer, get_line (line_number)); if (x_pos > strlen (buffer)) x_pos = strlen (buffer); left_col = x_pos - (COLS - 1); if (left_col < 0) left_col = 0; show_list (top_line, left_col, y, x); } break; case (KEY_PPAGE): if (line_number == 0) break; /* Removed all the beeps. */ else { if (line_number >= lines) { add_line (buffer, line_number); ++lines; } else modify_line (buffer, line_number); if (y == 0) { line_number -= (LINES - 1); if (line_number < 0) line_number = 0; top_line = line_number; y = 0; } else { y = 0; line_number = top_line; if (line_number < 0) { line_number = 0; y = 0; } } strcpy (buffer, get_line (line_number)); if (x_pos > strlen (buffer)) x_pos = strlen (buffer); left_col = x_pos - (COLS - 1); if (left_col < 0) left_col = 0; show_list (top_line, left_col, y, x); } break; case (KEY_F0 + 1): /* F1 key exits */ move (11, 0); clrtoeol (); move (13, 0); clrtoeol (); move (12, 0); clrtoeol (); addstr ("Do you really want to quit? (Y/N)"); refresh (); c = getch (); if (c == 'y' || c == 'Y') finish (0); move (y, x_pos - left_col); show_list (top_line, left_col, y, x); break; case (KEY_F0 + 12): /* F12 saves the file */ save_err = 0; if (line_number >= lines) { add_line (buffer, line_number); ++lines; } else modify_line (buffer, line_number); move (11, 0); clrtoeol (); move (13, 0); clrtoeol (); move (12, 0); clrtoeol (); while (strlen (file_name)) { addstr ("Save as "); for (count = 0; count < strlen (file_name); count++) addch (file_name[count]); addstr ("? (Y/N)"); refresh (); c = getch (); if (c == 'y' || c == 'Y') {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -