📄 macro.c
字号:
* find the first keystroke in the macro. when we pop the stack, * all this stuff is reset by the pop -- do not reset it again. */ g_status.macro_next = 0; mac = g_status.current_macro = g_status.key_macro; mode.insert = mac->mode[0]; mode.smart_tab = mac->mode[1]; mode.indent = mac->mode[2]; g_status.macro_mark.marked = FALSE; if (mac->flag & USESBLOCK) { block.marked = g_status.marked; block.file = g_status.marked_file; block.type = file->block_type; block.bc = file->block_bc; block.br = file->block_br; block.ec = file->block_ec; block.er = file->block_er; unmark_block( window ); } } popped = recursed = FALSE; while (rc != ERROR && g_status.macro_next < mac->len) { /* * set up all editor variables as if we were entering * keys from the keyboard. */ window = g_status.current_window; display_dirty_windows( window ); CEH_OK; g_status.key_pressed = (mac->len == 1) ? mac->key.key : mac->key.keys[g_status.macro_next]; g_status.command = getfunc( g_status.key_pressed ); if (g_status.wrapped) { g_status.wrapped = FALSE; show_search_message( CLR_SEARCH ); } if (found_rline) { found_rline = 0; show_curl_line( window ); } /* * while there are no errors or Control-Breaks, let's keep on * executing a macro. g_status.control_break is a global * editor flag that is set in our Control-Break interrupt * handler routine. */ if (g_status.control_break == TRUE) { rc = ERROR; break; } /* * we haven't called any editor function yet. we need * to look at the editor command that is to be executed. * if the command is PlayBack, we need to break out of * this inner do loop and start executing the macro * from the beginning (the outer do loop). * * if we don't break out now from a recursive macro, we will * recursively call PlayBack and we will likely overflow * the main (as opposed to the macro) stack. */ if (g_status.command == PlayBack || g_status.command == PseudoMacro) { if (g_status.command == PseudoMacro) { if ((pkey = find_combination( window )) == 0 || (pmac = find_pseudomacro( pkey, window )) == NULL) { ++g_status.macro_next; continue; } g_status.key_macro = pmac; } /* * recursive macros are handled differently from * macros that call other macros. * recursive macros - continue the macro from the beginning. * standard macros - save the next instruction of this * macro on the stack and begin executing the called macro. */ if (g_status.current_macro != g_status.key_macro) { if (push_macro_stack( ) != OK) { error( WARNING, window->bottom_line, ed16 ); rc = ERROR; } recursed = TRUE; break; } else { if (file->break_point != 0 && file->break_point == window->rline) { rc = ERROR; break; } g_status.macro_next = 0; continue; } } ++g_status.macro_next; rc = execute( window ); /* * jmh - A recursive macro that is closing windows could * close the editor. */ if (g_status.stop == TRUE) rc = ERROR; } /* * restore the block, irrespective of how the macro finished. */ if (!recursed && !g_status.stop && (mac->flag & USESBLOCK)) { unmark_block( window ); g_status.marked_file = block.file; g_status.marked = block.marked; file->block_type = block.type; file->block_bc = block.bc; file->block_br = block.br; file->block_ec = block.ec; file->block_er = block.er; if (g_status.marked && g_status.marked_file != file) { g_status.marked_file->dirty = GLOBAL; g_status.marked_file->block_type = -block.file->block_type; } } /* * A recursive macro will always finish with an error condition. * Make it OK instead, to allow other macros to call it and continue. */ if (g_status.current_macro == g_status.key_macro && !g_status.stop && !g_status.control_break) { rc = OK; g_status.macro_next = mac->len; } /* * If the macro finished, goto the marker if one was set. * If there's nothing on the stack, then get out. */ if (rc != ERROR && g_status.macro_next == mac->len) { g_status.command = MacroMark; goto_marker( window ); if (g_status.mstack == NULL) rc = ERROR; else if (pop_macro_stack( ) != OK) { error( WARNING, window->bottom_line, ed17 ); rc = ERROR; } else { popped = TRUE; mac = g_status.current_macro; } } } /* * If the macro successfully finished, the last command * will be MacroMark. */ if (g_status.command == MacroMark) rc = OK; /* * If the macro was aborted, tidy up the macro stack. */ else while (g_status.mstack != NULL) { MACRO_STACK *ms = g_status.mstack; g_status.mstack = ms->prev; free( ms ); } g_status.macro_executing = FALSE; mode.insert = cur_mode[0]; mode.smart_tab = cur_mode[1]; mode.indent = cur_mode[2]; if (!mode.record) { show_insert_mode( ); show_tab_modes( ); show_indent_mode( ); } } if (old_ms != NULL) { g_status.mstack = old_ms; g_status.macro_executing = TRUE; g_status.current_macro = ms.macro; g_status.macro_next = ms.pos; g_status.macro_mark = ms.mark; } return( rc );}/* * Name: push_macro_stack * Purpose: push the next key in a currently executing macro on local stack * Date: October 31, 1992 * Notes: finally got tired of letting macros only "jump" and not call * other macros. * the first time in, mstack is NULL. * Rewritten by Jason Hood, July 18, 1998. */int push_macro_stack( void ){MACRO_STACK *ms; /* * first, make sure we have room to push the key. */ if ((ms = malloc( sizeof(MACRO_STACK) )) != NULL) { /* * Store the current macro, its next key and its marker. * Point to the previous macro on the stack and make this macro * the top of the stack. */ ms->macro = g_status.current_macro; ms->pos = g_status.macro_next+1; ms->mark = g_status.macro_mark; ms->block = block; ms->prev = g_status.mstack; g_status.mstack = ms; return( OK ); } else return( STACK_OVERFLOW );}/* * Name: pop_macro_stack * Purpose: pop currently executing macro on local stack * Date: October 31, 1992 * Notes: finally got tired of letting macros only "jump" and not "call" * other macros. * pop the macro stack. stack pointer is pointing to last key saved * on stack. * Rewritten by Jason Hood, July 18, 1998. */int pop_macro_stack( void ){MACRO_STACK *ms = g_status.mstack; /* * before we pop the stack, make sure there is something in it. */ if (ms != NULL) { /* * Pop the macro, its position and marker. Point to the previous macro. * Restore the editor modes to the original macro. */ g_status.current_macro = ms->macro; g_status.macro_next = ms->pos; g_status.macro_mark = ms->mark; block = ms->block; g_status.mstack = ms->prev; free( ms ); mode.insert = g_status.current_macro->mode[0]; mode.smart_tab = g_status.current_macro->mode[1]; mode.indent = g_status.current_macro->mode[2]; return( OK ); } else return( STACK_UNDERFLOW );}/* * Name: macro_pause * Purpose: Enter pause state for macros * Date: June 5, 1992 * Passed: arg_filler: argument to satisfy function prototype * Returns: ERROR if the ESC key was pressed, OK otherwise. * Notes: this little function is quite useful in macro definitions. if * it is called near the beginning of a macro, the user may decide * whether or not to stop the macro. * * jmh 980525: only pause if a macro is recording or playing. * jmh 031114: don't display halt message if recording; * test being called from a prompt */int macro_pause( TDE_WIN *arg_filler ){long c = 0; /* 0 != ESC so returns OK if no macro */ if (mode.record || g_status.macro_executing) { /* * tell user we are paused. */ s_output( paused1, g_display.mode_line, 22, Color( Special ) ); s_output( (mode.record) ? paused1a : paused2, g_display.mode_line, 22 + strlen( paused1 ), Color( Mode ) ); /* * get the user's response and restore the mode line. */ if (g_status.command == Pause) { c = getkey( ); show_modes( ); } } return( c == ESC ? ERROR : OK );}/* * Name: getkey_macro * Purpose: read a key from a macro or the keyboard * Author: Jason Hood * Date: July 26, 1998 * Passed: nothing * Returns: key read * Notes: If no macro is executing, or its next function is Pause, * or it is finished, read the key from the keyboard. * Record the key unless it's from a macro. * If the key read from the keyboard is the pause function, * and it's record mode, record it, wait for another key, * but don't record that. */long getkey_macro( void ){long key = ERROR;int func; if (g_status.macro_executing && g_status.macro_next < g_status.current_macro->len) { key = g_status.current_macro->key.keys[g_status.macro_next++]; if (getfunc( key ) == Pause) key = ERROR; } if (key == ERROR) { key = getkey( ); if (!g_status.macro_executing && mode.record) { func = getfunc( key ); record_key( key, func ); if (func == Pause) key = getkey( ); } } return( key );}/* * Name: set_break_point * Purpose: set or remove a break point * Author: Jason Hood * Date: August 15, 1998 * Passed: window: pointer to current window * Notes: if the break point is already set, either move it to the new * line, or clear it. * The break-point is used to stop recursive/infinite macros, * or an infinite repeat. * * jmh 991006: moved from findrep.c, since searches no longer use it. */int set_break_point( TDE_WIN *window){file_infos *file; if (window->ll->len == EOF) return( ERROR ); file = window->file_info; file->break_point = (file->break_point == window->rline) ? 0 : window->rline; file->dirty = GLOBAL; return( OK );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -