📄 mined1.c
字号:
/* ================================================================== * * Editor mined * * Part 1 * * for documentation see mined.doc * * ================================================================== */#include "mined.h"/* #define DEBUG *//* ================================================================== * * Definitions specific for mined1.c * * ================================================================== */#ifndef helpcommand# ifdef unix# define helpcommand "man mined"# endif# ifdef vms# define helpcommand "help mined"# endif# ifdef msdos# define helpcommand "more < %smined.hlp"# endif#endif#ifndef printcommand# ifdef unix# ifdef sysV# define printcommand "lp %s"# else# define printcommand "lpr %s"# endif# endif# ifdef vms# define printcommand "print %s"# endif# ifdef msdos# define printcommand "copy %s prn: > nul:"# endif#endif/* ================================================================== * * Data section * * ================================================================== */LINE * header; /* Head of line list */LINE * tail; /* Last line in line list */LINE * cur_line; /* Current line in use */LINE * top_line; /* First line of screen */LINE * bot_line; /* Last line of screen */char * cur_text; /* Current char on current line in use */int last_y; /* Last y of screen. Usually SCREENMAX */int x = 0, y = 0; /* x, y coordinates on screen */short YMAX, XMAX;char screen [screen_BUFL + 1]; /* I/O buffer for "writes" and "reads" */int total_lines = 0; /* Number of lines in file */long total_chars = -1L; /* Number of characters in file */FLAG modified = FALSE; /* Set when file is modified */FLAG viewonly = FALSE; /* Set when view only mode is selected */FLAG overwriteOK = FALSE; /* Set if current file is OK for overwrite */FLAG writable; /* Set if file cannot be written */FLAG loading = TRUE; /* Loading a file? Init TRUE for error handling */FLAG quit = FALSE; /* Set when quit character is typed */FLAG intr_char = FALSE; /* Set when intr character is typed */FLAG winchg = FALSE; /* Set when window size has changed */FLAG isscreenmode = FALSE; /* Set when screen mode is on */FLAG stat_visible; /* Set if status_line is visible */FLAG fstat_always = FALSE; /* Permanent file status display wanted ? */FLAG waitingforinput = FALSE; /* Set while waiting for the next command key */FLAG rpipe = FALSE; /* Set if file should be read from stdin */FLAG wpipe = FALSE; /* Set if file should be written to stdout */FLAG multiexit = TRUE; /* Should exit command go to next file? */FLAG proportional = FALSE; /* Enable support for proportional fonts? */FLAG controlQS = FALSE; /* must respect ^Q/^S handshake ? */FLAG insert_mode = TRUE; /* insert or overwrite */uchar control_prefix = '\026'; /* ^V/^P character to prefix control chars */FLAG Chinese = FALSE; /* set if two-byte characters are enabled */FLAG page_scroll = FALSE; /* use scroll for page up/down */FLAG page_stay = FALSE; /* stay at edge of screen after page up/down */#ifdef pcint display_delay = 9; /* delay between display lines */#elseint display_delay = -1; /* Unix terminals are slow enough anyway */#endif#ifdef msdoschar RET_opt = 'r'; /* handle RET chars: ignore / newline */#elsechar RET_opt = ' '; /* handle RET chars: ignore / newline */#endiflong chars_saved; /* Nr of chars in buffer */int input_fd = STD_IN; /* File descriptors for terminal dialog */int output_fd = STD_ERR;int out_count = 0; /* Index in output buffer */char file_name [maxLINE_LEN]; /* Name of file in use */char text_buffer [MAX_CHARS]; /* for get_line, modifications, build_string */int hop_flag = 0; /* Counter for the HOP function */char TABchar = ' '; /* Char to be shown in place of tab chars */char SHIFT_BEG = '\0'; /* Char indicating that line continues left */char RET_MARK = '\0'; /* Char indicating end of line */char RET_BLANK = '\0'; /* Char to fill the end of line with */char RET_BLANK2 = '\0'; /* Char to fill last position of line with */#ifdef vmsint fprot = 0; /* To be used for file creatings */int bufprot = 0; /* To be used for paste buffer file */#elseint fprot = 0644; /* To be used for file creatings */int bufprot = 0600; /* To be used for paste buffer file */#endifint fnami; /* Parameter index of current file name */int fnami_min, fnami_max, fnami_cnt;/* char * (* fnamv) []; */char * * fnamv; /* Copy of argv. Points to program params */int left_margin = 0;int right_margin = 71;/* * Yank variables. */char * temp_dir;char yank_file [maxLINE_LEN];char yankie_file [maxLINE_LEN];char panic_file [maxLINE_LEN];char mined_dir [maxLINE_LEN]; /* startup directory to locate help file *//* ================================================================== * * Text buffer routines * * ================================================================== */int old_x = 0; /* previous x position *//* * Find_x () returns the x coordinate belonging to address. * (Tabs are expanded). */intfind_x (line, address) LINE * line; char * address;{ register char * textp = line->text; register int x_left = get_shift (line->shift_count) * - SHIFT_SIZE; register int x_in_line = 0; /* must start from 0 to calculate correct tab positions (since SHIFT_SIZE is not guaranteed to be a multiple of 8) */ /* Alright, SHIFT_SIZE is now guaranteed to be a multiple of 8 due to lots of display problems related to that matter. Leave this code anyway. */ while (textp != address && * textp != '\0') { if (is_tab (* textp ++)) /* Expand tabs */ x_in_line = tab (x_in_line); else x_in_line ++; } return x_in_line + x_left;}/* * Find_address () returns the pointer in the line with given offset. * (Tabs are expanded). * find_address is only called by move_it ()get_shift (cnt) is ((cnt) & DUMMY_MASK) ; DUMMY_MASK is 0x7Ftab (cnt) is (((cnt) + 8) & ~07)is_tab (c) is ((c) == '\t') */char *find_address (line, new_x, cur_x) LINE * line; int new_x; int * cur_x;{ register char * textp = line->text; register int tx = get_shift (line->shift_count) * - SHIFT_SIZE; while (tx < new_x && * textp != '\n') { if (is_tab (* textp)) { if (new_x == old_x /* (* cur_x) */ - 1 && tab (tx) > new_x) break; /* Moving left over tab */ else tx = tab (tx); } else tx ++; textp ++; } * cur_x = tx; return textp;}/* * inmultichar (string, charpoi) determines if charpoi points to the second * byte of a multi-byte character within string */intinmultichar (string, charpoi) uchar * string; uchar * charpoi;{ while (string < charpoi) { if (multichar (* string)) { string ++; if (* string != '\n' /* would be an error */) string ++; } else string ++; } return string > charpoi;}/* * move_to: move to given coordinates on screen. * move_y: move to given line on screen, staying in last explicit column. * move_address: move to given line at given text position. * The caller must check that scrolling is not needed. * If new x-position is < 0 or > XBREAK, move_it () will check if * the line can be shifted. If it can it sets (or resets) the shift_count * field of the current line accordingly. By this mechanism, the * pseudo-x-positions LINE_START / LINE_END (a very small / big value) * perform the appropriate positioning actions. * Move also sets cur_text to the right char. * "If we're moving to the same x coordinate, try to move the the x-coordinate * used on the other previous call." -- This worked erroneously and was * replaced by an explicit old_x variable and move_y call. * move_address is directly called by move_next/previous_word(), re_search(), RDwin() */voidmove_it (new_x, new_address, new_y) register int new_x; int new_y; char * new_address;{ register LINE * line = cur_line; /* For building new cur_line */ int shift = 0; /* How many shifts to make *//* static int rel_x = 0; */ /* Remember relative x position *//* This was used as a trick to stay virtually in the previous column even when moving across shorter lines; but it had >= 2 errors. Renamed to old_x, made globally accessible and explicitly used by appropriate calls to avoid these problems. TW */ int tx = x;/* Check for illegal values */ if (new_y < 0 || new_y > last_y) return;/* Adjust y-coordinate and cur_line */ if (new_y < y) while (y != new_y) { y --; line = line->prev; } else while (y != new_y) { y ++; line = line->next; }/* Set or unset relative x-coordinate */ if (new_address == NIL_PTR) { new_address = find_address (line, new_x, & tx); new_x = tx; } else /* rel_x = */ new_x = find_x (line, new_address);/* Adjust on character boundary */ if (Chinese == TRUE) { if (inmultichar (line->text, new_address)) { /* adjust position which is currently within a multi-byte character */ if (new_x >= x) { new_x ++; new_address ++; } else { new_x --; new_address --; } } }/* Adjust shift_count if new_x lower than 0 or higher than XBREAK *//* Allow adjustment also if new_x == 0 to enable left shift mark */ if (new_x <= 0 || new_x >= XBREAK) { if (new_x > XBREAK || (new_x == XBREAK && * new_address != '\n')) shift = (new_x - XBREAK) / SHIFT_SIZE + 1; else { shift = new_x / SHIFT_SIZE; if (new_x % SHIFT_SIZE) shift --; if (new_x == 0 && line->shift_count != 0 && SHIFT_BEG != '\0') shift --; } if (shift != 0) { line->shift_count += shift; new_x = find_x (line, new_address); if (new_x == 0 && line->shift_count != 0 && SHIFT_BEG != '\0') { line->shift_count --; new_x = find_x (line, new_address); } set_cursor (0, y); line_print (line); /* rel_x = new_x; */ } }/* Assign and position cursor */ x = new_x; cur_text = new_address; cur_line = line; set_cursor_xy ();}voidmove_y (ny) register int ny;{ move_it (old_x, NIL_PTR, ny);}voidmove_to (nx, ny) register int nx; register int ny;{ old_x = x; move_it (nx, NIL_PTR, ny); old_x = x;}voidmove_address (nadd, ny) register char * nadd; register int ny;{ old_x = x; move_it (0, nadd, ny); old_x = x;}/* * Initialize is called when a another file is edited. It free's the allocated * space and sets modified back to FALSE and fixes the header/tail pointer. */voidinitialize (){ register LINE * line, * next_line;/* Delete the whole list */ for (line = header->next; line != tail; line = next_line) { next_line = line->next; free_space (line->text); free_header (line); }/* header and tail should point to itself */ line->next = line->prev = line; x = y = 0; rpipe = modified = FALSE;}/* * Get_line reads one line from filedescriptor fd. If EOF is reached on fd, * get_line () returns ERRORS, else it returns the length of the string. */char * get_l_err1;char * get_l_err2;char last_char = '\0';intget_line (fd, buffer) int fd; register char buffer [MAX_CHARS];{ static char * last = NIL_PTR; static char * current = NIL_PTR; static int read_chars; register char * cur_pos = current; char * begin = buffer; char * fini = buffer + MAX_CHARS - 2 /* leave space for '\n\0' */; register FLAG ignore1char; do { do { ignore1char = FALSE; if (cur_pos == last) { if ((read_chars = read (fd, screen, screen_BUFL)) <= 0) break; last = & screen [read_chars]; cur_pos = screen; } if (* cur_pos == '\0' ) { get_l_err1 = "File contains NULL char's - changed to DEL's - "; * cur_pos = '\177'; }#ifdef msdos if (* cur_pos == '\n' && last_char != '\r') modified = TRUE;#endif if (RET_opt == 'R' && * cur_pos == '\n' && last_char == '\r') { last_char = * cur_pos; cur_pos ++; ignore1char = TRUE; modified = TRUE; } else last_char = * cur_pos; if (* cur_pos == '\r' ) { if (RET_opt == 'R') { * cur_pos = '\n'; modified = TRUE; } else if (RET_opt == 'r') { cur_pos ++; ignore1char = TRUE;#ifndef msdos modified = TRUE;#endif } } } while (ignore1char == TRUE); if (cur_pos == last) break; if (buffer == fini && * cur_pos != '\n') { get_l_err2 = "Line too long - split"; * buffer ++ = '\n'; break; } } while ((* buffer ++ = * cur_pos ++) != '\n'); current = cur_pos; if (read_chars <= 0) { if (buffer == begin) return ERRORS; if (* (buffer - 1) != '\n') if (loading == TRUE) /* Add '\n' to last line of file */ * buffer ++ = '\n'; else { * buffer = '\0'; return NO_LINE; } } * buffer = '\0'; return (int) (buffer - begin);}/* * Load_file loads the file with given name or the input pipe into memory. * If the file couldn't be opened, just an empty line is installed. * Buffer pointers are initialized. */voidload_file_w_o_display (file) char * file;{ register LINE * line = header; register int len; long nr_of_chars = 0L; int fd = -1; /* Filedescriptor for file */ total_lines = 0; /* Zero lines to start with */ overwriteOK = FALSE;/* Open file */ writable = TRUE; /* Benefit of the doubt */ if (file == NIL_PTR) { if (rpipe == FALSE) status_msg ("No file"); else { fd = 0; file = "standard input"; } file_name [0] = '\0'; } else { copy_string (file_name, file); /* Save file name */ if (access (file, 0 /* F_OK */) < 0) { /* Cannot access file */ status_line ("New file ", file); overwriteOK = TRUE; } else if ((fd = open (file, O_RDWR | O_BINARY, 0)) >= 0) { overwriteOK = TRUE; writable = TRUE; } else if ((fd = open (file, O_RDONLY | O_BINARY, 0)) < 0) error ("Cannot open: " /*, file */, serror ()); else { overwriteOK = TRUE; writable = FALSE; } }/* Read file */ loading = TRUE; /* Loading file, so set flag */ get_l_err1 = NIL_PTR; get_l_err2 = NIL_PTR; if (fd >= 0) { status_line ("Reading ", file); while (line != NIL_LINE && (len = get_line (fd, text_buffer)) != ERRORS) { line = line_insert (line, text_buffer, len); nr_of_chars += (long) len; } if (total_lines == 0 && line != NIL_LINE) /* The file was empty! */ line = line_insert (line, "\n", 1); clear_buffer (); /* Clear output buffer: out_count = 0; */ cur_line = header->next; (void) close (fd); /* Close file */ if (line != NIL_LINE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -