/* * Name: save_strokes * Purpose: save strokes to a file * Date: April 1, 1992 * Passed: window: pointer to current window */ int save_strokes( WINDOW *window ) { FILE *fp; /* file to be written */ char name[MAX_COLS+2]; /* file name */ char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */ register int rc; int prompt_line; int fattr; name[0] = '\0'; prompt_line = window->bottom_line; save_screen_line( 0, prompt_line, line_buff ); /* * name for macro file */ if ((rc = get_name( main19, prompt_line, name, g_display.message_color )) == OK && *name != '\0') { /* * make sure it is OK to overwrite any existing file */ rc = get_fattr( name, &fattr ); if (rc == OK) { /* * overwrite existing file */ set_prompt( main20, prompt_line ); if (get_yn( ) != A_YES || change_mode( name, prompt_line ) == ERROR) rc = ERROR; } if (rc != ERROR) { if ((fp = fopen( name, "wb" )) != NULL) { fwrite( ¯o.first_stroke[0], sizeof(int), MAX_KEYS, fp ); fwrite( ¯o.strokes[0], sizeof(STROKES), STROKE_LIMIT, fp ); fclose( fp ); } } } restore_screen_line( 0, prompt_line, line_buff ); return( OK ); }
/* * Name: record_on_off * Purpose: save keystrokes in keystroke buffer * Date: April 1, 1992 * Passed: window: pointer to current window * Notes: -1 in .next field indicates the end of a recording * -1 in .key field indicates the initial, unassigned macro key * STROKE_LIMIT+1 in .next field indicates an unused space. */ int record_on_off( WINDOW *window ) { register int next; int prev; int line; int key; int func; char line_buff[(MAX_COLS+2)*2]; /* buffer for char and attribute */ mode.record = !mode.record; if (mode.record == TRUE) { line = window->bottom_line; show_avail_strokes( ); save_screen_line( 0, line, line_buff ); /* * press key that will play back recording */ set_prompt( main11, line ); /* * get the candidate macro key and look up the function assigned to it. */ key = getkey( ); func = getfunc( key ); /* * the key must be an unused, recognized function key or a function * key assigned to a previously defined macro. we also need room * in the macro structure. */ if (key <= 256 || (func != 0 && func != PlayBack)) { /* * cannot assign a recording to this key */ error( WARNING, line, main12 ); mode.record = FALSE; } else if (g_status.stroke_count == 0) { /* * no more room in recording buffer */ error( WARNING, line, main13 ); mode.record = FALSE; } else { /* * everything is everything so far, just check for a prev macro */ prev = OK; if (func == PlayBack) { /* * overwrite recording (y/n)? */ set_prompt( main14, line ); if (get_yn( ) == A_NO) { prev = ERROR; mode.record = FALSE; } } if (prev == OK) { g_status.recording_key = key; next = macro.first_stroke[key-256]; /* * if key has already been assigned to a macro, clear macro def. */ if (next != STROKE_LIMIT+1) { do { prev = next; next = macro.strokes[next].next; macro.strokes[prev].key = MAX_KEYS+1; macro.strokes[prev].next = STROKE_LIMIT+1; ++g_status.stroke_count; } while (next != -1); show_avail_strokes( ); } /* * find the first open space and initialize */ for (next=0; macro.strokes[next].next != STROKE_LIMIT+1;) next++; macro.first_stroke[key-256] = next; macro.strokes[next].key = -1; macro.strokes[next].next = -1; key_func.key[key-256] = PlayBack; /* * recording */ s_output( main15, g_display.mode_line, 22, g_display.mode_color | 0x80 ); } } restore_screen_line( 0, line, line_buff ); } /* * the flashing "Recording" and the stroke count write over the modes. * when we get thru defining a macro, redisplay the modes. */ if (mode.record == FALSE) { memset( line_buff, ' ', 36 ); line_buff[36] = '\0'; s_output( line_buff, g_display.mode_line, 22, g_display.mode_color ); show_tab_modes( ); show_indent_mode( ); show_sync_mode( ); show_search_case( ); show_wordwrap_mode( ); /* * let's look at the macro. if the first .key of the macro is * still -1, which is the initial unassigned key in a macro, reset * the macro so other keys may be assigned to this node. */ key = g_status.recording_key; if (key != 0) { next = macro.first_stroke[key-256]; if (macro.strokes[next].key == -1) { macro.strokes[next].key = MAX_KEYS+1; macro.strokes[next].next = STROKE_LIMIT+1; macro.first_stroke[key-256] = STROKE_LIMIT+1; if (getfunc( key ) == PlayBack) key_func.key[key-256] = 0; } } g_status.recording_key = 0; } return( OK ); }
/* * Name: differ * Purpose: diff text pointers * Date: October 31, 1992 * Passed: initial_rcol1: beginning column to begin diff in window1 * initial_rcol2: beginning column to begin diff in window2 * bottom: line to display diagnostics * Notes: a straight diff on text pointers is simple; however, diffing * with leading spaces and tabs is kinda messy. let's do the * messy diff. */ int differ( int initial_rcol1, int initial_rcol2, int bottom ) { int rcol1; /* virtual real column on diff window 1 */ int rcol2; /* virtual real column on diff window 2 */ int r1; /* real real column rcol1 - needed for tabs */ int r2; /* real real column rcol2 - needed for tabs */ char c1; /* character under r1 */ char c2; /* character under r2 */ int leading1; /* adjustment for leading space in window 1 */ int leading2; /* adjustment for leading space in window 2 */ int len1; /* length of diff1 line */ int len2; /* length of diff2 line */ line_list_ptr node1; /* scratch node in window 1 */ line_list_ptr node2; /* scratch node in window 2 */ text_ptr diff1; /* scratch text ptr in window 1 */ text_ptr diff2; /* scratch text ptr in window 2 */ long rline1; /* real line number of diff pointer 1 */ long rline2; /* real line number of diff pointer 2 */ long bin_offset1; /* binary offset of diff pointer 1 */ long bin_offset2; /* binary offset of diff pointer 2 */ int len; /* line length variable */ register int tabs; /* local variable for mode.inflate_tabs, T or F */ char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */ /* * initialize the text pointers and the initial column. skip any * initial blank lines. */ rline1 = diff.rline1; rline2 = diff.rline2; node1 = diff.d1; node2 = diff.d2; bin_offset1 = diff.bin_offset1; bin_offset2 = diff.bin_offset2; tabs = mode.inflate_tabs; if (diff.blank_lines) { while (node1->len != EOF && is_line_blank( node1->line, node1->len )) { bin_offset1 += node1->len; node1 = node1->next; ++rline1; initial_rcol1 = 0; } while (node2->len != EOF && is_line_blank( node2->line , node2->len)) { bin_offset2 += node2->len; node2 = node2->next; ++rline2; initial_rcol2 = 0; } } /* * if everything is everything, initialize the diff variables and diff. */ if (node1->len != EOF && node2->len != EOF) { diff1 = node1->line; diff2 = node2->line; rcol1 = initial_rcol1; rcol2 = initial_rcol2; len1 = node1->len; len2 = node2->len; assert( rcol1 >= 0 ); assert( rcol1 < MAX_LINE_LENGTH ); assert( rcol2 >= 0 ); assert( rcol2 < MAX_LINE_LENGTH ); assert( len1 >= 0 ); assert( len1 < MAX_LINE_LENGTH ); assert( len2 >= 0 ); assert( len2 < MAX_LINE_LENGTH ); /* * if cursors are past EOL, move them back to EOL. */ len = find_end( diff1, len1 ); if (rcol1 > len) rcol1 = len; len = find_end( diff2, len2 ); if (rcol2 > len) rcol2 = len; /* * if skip leading space, make sure our cursors start on first non-space. */ if (diff.leading) { leading1 = skip_leading_space( diff1, len1 ); leading2 = skip_leading_space( diff2, len2 ); if (tabs) { leading1 = detab_adjust_rcol( diff1, leading1 ); leading2 = detab_adjust_rcol( diff2, leading2 ); } if (rcol1 < leading1) rcol1 = leading1; if (rcol2 < leading2) rcol2 = leading2; } /* * we now have a valid rcol for the diff start, we may need to adjust * for tabs, though. */ assert( rcol1 >= 0 ); assert( rcol1 < MAX_LINE_LENGTH ); assert( rcol2 >= 0 ); assert( rcol2 < MAX_LINE_LENGTH ); r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1; r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2; assert( r1 >= 0 ); assert( r1 <= len1 ); assert( r2 >= 0 ); assert( r2 <= len2 ); assert( r1 <= rcol1 ); assert( r2 <= rcol2 ); s_output( diff_message, g_display.mode_line, 67, g_display.diag_color ); while (node1->len != EOF && node2->len != EOF && !g_status.control_break) { /* * look at each character in each diff window */ c1 = (char)(r1 < len1 ? *(diff1 + r1) : 0); c2 = (char)(r2 < len2 ? *(diff2 + r2) : 0); /* * tabs == space */ if (tabs) { if (c1 == '\t') c1 = ' '; if (c2 == '\t') c2 = ' '; } /* * skip spaces, if needed */ if (diff.all_space) { while (c1 == ' ' && r1 < len1) { ++rcol1; r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1; c1 = (char)(r1 < len1 ? *(diff1 + r1) : 0); if (c1 == '\t' && tabs) c1 = ' '; } while (c2 == ' ' && r2 < len2) { ++rcol2; r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2; c2 = (char)(r2 < len2 ? *(diff2 + r2) : 0); if (c2 == '\t' && tabs) c2 = ' '; } } /* * if one of the node pointers has come to EOL, move to next * diff line. */ if (diff.ignore_eol) { if (r1 >= len1) { node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 ); len1 = node1->len; if (len1 != EOF) { diff1 = node1->line; c1 = (char)(r1 < len1 ? *(diff1 + r1) : 0); if (c1 == '\t' && tabs) c1 = ' '; } } if (r2 >= len2) { node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 ); len2 = node2->len; if (len2 != EOF) { diff2 = node2->line; c2 = (char)(r2 < len2 ? *(diff2 + r2) : 0); if (c2 == '\t' && tabs) c2 = ' '; } } } /* * convert the characters to lower case, if needed. */ if (mode.search_case == IGNORE) { c1 = (char)tolower( c1 ); c2 = (char)tolower( c2 ); } /* * diff each character in the diff lines until we reach EOL */ while (r1 < len1 && r2 < len2) { if (c1 == c2) { if (diff.all_space) { do { ++rcol1; r1 = tabs ? entab_adjust_rcol( diff1,len1,rcol1 ) : rcol1; c1 = (char)(r1 < len1 ? *(diff1 + r1) : 0); if (c1 == '\t' && tabs) c1 = ' '; } while (c1 == ' ' && r1 < len1); do { ++rcol2; r2 = tabs ? entab_adjust_rcol( diff2,len2,rcol2 ) : rcol2; c2 = (char)(r2 < len2 ? *(diff2 + r2) : 0); if (c2 == '\t' && tabs) c2 = ' '; } while (c2 == ' ' && r2 < len2); } else { ++rcol1; ++rcol2; r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1; r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2; c1 = (char)(r1 < len1 ? *(diff1 + r1) : 0); c2 = (char)(r2 < len2 ? *(diff2 + r2) : 0); if (tabs) { if (c1 == '\t') c1 = ' '; if (c2 == '\t') c2 = ' '; } } if (diff.ignore_eol) { if (r1 >= len1) { node1 = skip_eol(node1, &r1, &rcol1, &rline1,&bin_offset1); len1 = node1->len; if (len1 != EOF) { diff1 = node1->line; c1 = (char)(r1 < len1 ? *(diff1 + r1) : 0); if (c1 == '\t' && tabs) c1 = ' '; } } if (r2 >= len2) { node2 = skip_eol(node2, &r2, &rcol2, &rline2,&bin_offset2); len2 = node2->len; if (len2 != EOF) { diff2 = node2->line; c2 = (char)(r2 < len2 ? *(diff2 + r2) : 0); if (c2 == '\t' && tabs) c2 = ' '; } } } if (mode.search_case == IGNORE) { c1 = (char)tolower( c1 ); c2 = (char)tolower( c2 ); } } else { /* * when we show the diff, use rcol1 and rcol2, as * find_adjust does not adjust rcol for tabs. */ update_line( diff.w1 ); diff.w1->bin_offset = bin_offset1; find_adjust( diff.w1, node1, rline1, rcol1 ); check_virtual_col( diff.w1, rcol1, rcol1 ); show_diff_window( diff.w1 ); update_line( diff.w2 ); diff.w2->bin_offset = bin_offset2; bin_offset_adjust( diff.w2, rline2 ); find_adjust( diff.w2, node2, rline2, rcol2 ); check_virtual_col( diff.w2, rcol2, rcol2 ); show_diff_window( diff.w2 ); s_output( diff_blank, g_display.mode_line, 67, g_display.mode_color ); return( OK ); } } /* * if we haven't come to the end of a file buffer, check the last * characters. see if pointers are at EOL. */ if (node1->len != EOF && node2->len != EOF) { if (rcol1 != len1 && rcol2 != len2) { update_line( diff.w1 ); diff.w1->bin_offset = bin_offset1; find_adjust( diff.w1, node1, rline1, rcol1 ); show_diff_window( diff.w1 ); update_line( diff.w2 ); diff.w2->bin_offset = bin_offset2; find_adjust( diff.w2, node2, rline2, rcol2 ); show_diff_window( diff.w2 ); s_output( diff_blank, g_display.mode_line, 67, g_display.mode_color ); return( OK ); } else { node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 ); len1 = node1->len; diff1 = node1->line; node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 ); len2 = node2->len; diff2 = node2->line; } } assert( rcol1 >= 0 ); assert( rcol1 < MAX_LINE_LENGTH ); assert( rcol2 >= 0 ); assert( rcol2 < MAX_LINE_LENGTH ); assert( r1 >= 0 ); assert( r1 < MAX_LINE_LENGTH ); assert( r2 >= 0 ); assert( r2 < MAX_LINE_LENGTH ); assert( r1 <= rcol1 ); assert( r2 <= rcol2 ); if (node1->len == EOF) assert( len1 == EOF ); else { assert( len1 >= 0 ); assert( len1 < MAX_LINE_LENGTH ); } if (node2->len == EOF) assert( len2 == EOF ); else { assert( len2 >= 0 ); assert( len2 < MAX_LINE_LENGTH ); } } save_screen_line( 0, bottom, line_buff ); set_prompt( diff_prompt4, bottom ); getkey( ); restore_screen_line( 0, bottom, line_buff ); s_output( diff_blank, g_display.mode_line, 67, g_display.mode_color ); } return( ERROR ); }
/* * Name: size_window * Purpose: To change the size of the current and one other window. * Date: June 5, 1991 * Passed: window: pointer to current window * Notes: Use the Up and Down arrow keys to make the current window * bigger or smaller. The window above will either grow * or contract accordingly. */ int size_window( WINDOW *window ) { char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */ int func; int c; int resize; int show_above_ruler; int old_bottom_line; int old_top_line; int new_bottom_line; int new_top_line; register WINDOW *above; register WINDOW *win; win = window; if (win->top_line != 1 && !win->vertical) { entab_linebuff( ); un_copy_line( win->ll, win, TRUE ); save_screen_line( 0, win->bottom_line, line_buff ); /* * press up or down to change window size */ set_prompt( win4, win->bottom_line ); /* * resizing only affects current window and above visible window */ above = g_status.window_list; while (above->bottom_line + 2 != win->top_line || !above->visible) above = above->next; if (above->vertical) /* * cannot resize vertical window */ error( WARNING, win->bottom_line, win5 ); else { old_top_line = win->top_line; old_bottom_line = above->bottom_line; show_above_ruler = FALSE; for (func=0; func != AbortCommand && func != Rturn; ) { /* * If user has redined the ESC and Return keys, make them Rturn and * AbortCommand in this function. */ c = getkey( ); func = getfunc( c ); if (c == RTURN || func == NextLine || func == BegNextLine) func = Rturn; else if (c == ESC) func = AbortCommand; resize = FALSE; /* * if LineUp, make current window top line grow and bottom line * of above window shrink. if window movement covers up current * line of window then we must adjust logical line and real line. */ if (func == LineUp) { if (above->bottom_line > above->top_line + above->ruler) { if (win->rline == (win->cline - (win->top_line+win->ruler-1))) --win->cline; --win->top_line; if (above->cline == above->bottom_line) --above->cline; --above->bottom_line; resize = TRUE; if (mode.ruler) { if (win->ruler == FALSE) { if (win->cline == win->top_line) ++win->cline; if (win->cline > win->bottom_line) win->cline = win->bottom_line; win->ruler = TRUE; } } } /* * if LineDown, make current window top line shrink and bottom line * of above window grow. if window movement covers up current * line of window then we must adjust logical line and real line. */ } else if (func == LineDown) { if (win->bottom_line > win->top_line + win->ruler) { if (win->cline == win->top_line + win->ruler) ++win->cline; ++win->top_line; ++above->bottom_line; resize = TRUE; if (mode.ruler) { if (above->ruler == FALSE) { if (above->cline == above->top_line) ++above->cline; if (above->cline > above->bottom_line) above->cline = above->bottom_line; above->ruler = TRUE; make_ruler( above ); show_above_ruler = TRUE; } } } } /* * if we resize a window, then update window size and current and * real lines if needed. */ if (resize == TRUE) { setup_window( above ); display_current_window( above ); if (show_above_ruler) { show_ruler( above ); show_ruler_pointer( above ); show_above_ruler = FALSE; } setup_window( win ); show_window_header( win ); win->ruler = mode.ruler; make_ruler( win ); show_ruler( win ); show_ruler_pointer( win ); display_current_window( win ); save_screen_line( 0, win->bottom_line, line_buff ); /* * press up or down to change window size */ set_prompt( win4, win->bottom_line ); } } new_top_line = win->top_line; new_bottom_line = above->bottom_line; for (above=g_status.window_list; above != NULL; above=above->next) { if (!above->visible) { if (above->bottom_line == old_bottom_line) { above->bottom_line = new_bottom_line; if (above->cline < new_bottom_line) above->cline = new_bottom_line; setup_window( above ); } else if (above->top_line == old_top_line) { above->top_line = new_top_line; if (above->cline < new_top_line) above->cline = new_top_line; if ((long)(above->cline+1L - (above->top_line+above->ruler)) > above->rline) above->cline = (int)above->rline + above->top_line + above->ruler - 1; setup_window( above ); } } } } restore_screen_line( 0, win->bottom_line, line_buff ); } else { if (win->vertical) /* * cannot resize vertical window */ error( WARNING, win->bottom_line, win5 ); else /* * cannot resize top window */ error( WARNING, win->bottom_line, win6 ); } return( OK ); }
/* * Name: define_diff * Purpose: get info needed to initialize diff * Date: October 31, 1992 * Passed: window: pointer to current window * Notes: allow the user to start the diff at the beginning of the * file or at the current cursor location. once the diff * has been defined, the user may press one key to diff again. * user may diff any two visible windows on the screen. */ int define_diff( WINDOW *window ) { int rc; char temp[MAX_COLS]; int num1; int let1; int num2; int let2; int start; char line_buff[(MAX_COLS+1)*2]; /* buffer for char and attribute */ char buff[MAX_COLS*2]; /* buffer for char and attribute */ /* * get window number and letter of the first diff window. then, * verify that window - does it exit? is it visible? */ *temp = '\0'; rc = get_name( diff_prompt1, window->bottom_line, temp, g_display.message_color ); if (rc == OK) { rc = verify_number( temp, &num1 ); if (rc == OK) rc = verify_letter( temp, &let1, &diff.w1 ); } else return( ERROR ); if (rc == ERROR) { combine_strings( buff, diff_prompt6a, temp, diff_prompt6b ); error( WARNING, window->bottom_line, buff ); return( ERROR ); } /* * get and verify the next window number and letter to diff. */ *temp = '\0'; rc = get_name( diff_prompt2, window->bottom_line, temp, g_display.message_color ); if (rc == OK) { rc = verify_number( temp, &num2 ); if (rc == OK) rc = verify_letter( temp, &let2, &diff.w2 ); } else return( ERROR ); if (rc == ERROR) { combine_strings( buff, diff_prompt6a, temp, diff_prompt6b ); error( WARNING, window->bottom_line, buff ); return( ERROR ); } /* * are leading spaces significant? */ save_screen_line( 0, window->bottom_line, line_buff ); set_prompt( diff_prompt7a, window->bottom_line ); start = get_yn( ); restore_screen_line( 0, window->bottom_line, line_buff ); if (start != ERROR) diff.leading = start == A_YES ? TRUE : FALSE; else return( ERROR ); /* * are all spaces significant? */ save_screen_line( 0, window->bottom_line, line_buff ); set_prompt( diff_prompt7b, window->bottom_line ); start = get_yn( ); restore_screen_line( 0, window->bottom_line, line_buff ); if (start != ERROR) { if (start == A_YES) diff.leading = diff.all_space = TRUE; else diff.all_space = FALSE; } else return( ERROR ); /* * are blank lines significant? */ save_screen_line( 0, window->bottom_line, line_buff ); set_prompt( diff_prompt7c, window->bottom_line ); start = get_yn( ); restore_screen_line( 0, window->bottom_line, line_buff ); if (start != ERROR) diff.blank_lines = start == A_YES ? TRUE : FALSE; else return( ERROR ); /* * is end of line significant? */ save_screen_line( 0, window->bottom_line, line_buff ); set_prompt( diff_prompt7d, window->bottom_line ); start = get_yn( ); restore_screen_line( 0, window->bottom_line, line_buff ); if (start != ERROR) diff.ignore_eol = start == A_YES ? TRUE : FALSE; else return( ERROR ); /* * now, find out were to start the diff -- beginning of file or * current cursor location. */ save_screen_line( 0, window->bottom_line, line_buff ); set_prompt( diff_prompt3, window->bottom_line ); start = get_bc( ); restore_screen_line( 0, window->bottom_line, line_buff ); if (start != ERROR) { entab_linebuff( ); if (un_copy_line( window->ll, window, TRUE ) == ERROR) return( ERROR ); /* * if everything is everything, initialize the diff pointers. */ diff.defined = TRUE; if (start == BEGINNING) { diff.d1 = diff.w1->file_info->line_list; diff.d2 = diff.w2->file_info->line_list; diff.rline1 = 1L; diff.rline2 = 1L; diff.bin_offset1 = 0; diff.bin_offset2 = 0; rc = differ( 0, 0, window->bottom_line ); } else { diff.d1 = diff.w1->ll; diff.d2 = diff.w2->ll; diff.rline1 = diff.w1->rline; diff.rline2 = diff.w2->rline; diff.bin_offset1 = diff.w1->bin_offset; diff.bin_offset2 = diff.w2->bin_offset; rc = differ( diff.w1->rcol, diff.w2->rcol, window->bottom_line ); } } return( rc ); }