📄 macro.c
字号:
while (twokey != NULL) { write_twokeymacro( file, twokey->left ); if (twokey->macro != NULL) { fprintf( file, "%s %s", key_name( twokey->key, buf ), func_str[PlayBack] ); write_macro( file, twokey->macro, twokey->key ); } twokey = twokey->right; }}/* * Name: key_name * Purpose: determine the string associated with a key * Author: Jason Hood * Date: August 21, 1998 * Passed: key: key number to convert * buffer: place to store the string * Returns: buffer * Notes: minimum buffer size should be KEY_STR_MAX characters (see config.h) * * 990428: place ';' in quotes. * recognize the viewer keys. * 990429: write '"' correctly (""""). */char *key_name( long key, char *buffer ){int twokey;int j = 0; twokey = PARENT_KEY( key ); if (twokey) { j = strlen( key_name( twokey, buffer ) ); buffer[j++] = ' '; key = CHILD_KEY( key ); } if (key & _SHIFT) { buffer[j++] = 's'; buffer[j++] = '+'; } if (key & _CTRL) { buffer[j++] = 'c'; buffer[j++] = '+'; } if (key & _ALT) { buffer[j++] = 'a'; buffer[j++] = '+'; } strcpy( buffer+j, cfg_key[KEY( key )] ); return( buffer );}/* * Name: clear_macros * Purpose: reset all macro buffers, pointers, functions. * Date: April 1, 1992 * Notes: reset the available macro stroke count. reset all fields in * macro structure. clear any keys assigned to macros in the * function assignment array. * July 17, 1998 (jmh): if syntax highlighting is on, only clear the * language macros; conversely, if syntax highlighting * is off, only clear the global macros. */int clear_macros( TDE_WIN *window ){register int i, j;TREE *tree; if (!window->syntax) { for (j = 0; j < MODIFIERS; ++j) { for (i = 0; i < MAX_KEYS; i++) { if (macro[j][i] != NULL) { my_free( macro[j][i]->key.keys ); my_free( macro[j][i] ); macro[j][i] = NULL; key_func[j][i] = 0; } } } tree = &key_tree; } else tree = &window->file_info->syntax->key_tree; delete_pseudomacro( tree->left ); tree->left = NULL; delete_twokeymacro( tree->right ); return( OK );}/* * Name: delete_pseudomacro * Purpose: remove the pseudo-macro tree * Author: Jason Hood * Date: July 17, 1998 * Passed: tree: tree to be deleted * Notes: recursively delete all pseudo-macros */void delete_pseudomacro( TREE *tree ){ if (tree == NULL) return; if (tree->left == NULL && tree->right == NULL) { if (tree->macro != NULL) { if (tree->macro->len > 1) my_free( tree->macro->key.keys ); my_free( tree->macro ); } my_free( tree ); } else { delete_pseudomacro( tree->left ); tree->left = NULL; delete_pseudomacro( tree->right ); tree->right = NULL; delete_pseudomacro( tree ); }}/* * Name: delete_twokeymacro * Purpose: delete all two-key macros * Author: Jason Hood * Date: July 30, 1998 * Passed: tree: tree to be deleted * Notes: unlike delete_pseudomacro, this does not actually delete anything, * since the two-key functions need to be preserved. * 020819: remove tail recursion. */void delete_twokeymacro( TREE *tree ){ while (tree != NULL) { if (tree->macro != NULL) { if (tree->macro->len > 1) my_free( tree->macro->key.keys ); my_free( tree->macro ); tree->func = 0; tree->macro = NULL; } delete_twokeymacro( tree->left ); tree = tree->right; }}/* * keystroke play back functions *//* * Name: test_for_html * Class: macro helper function * Purpose: special pseudo-macro case for HTML * Author: Jason Hood * Date: June 1, 2001 * Passed: window: current window * Returns: TRUE if special case was found, ERROR otherwise. * Notes: if a pseudo-macro was not found, see if we're on a word that begins * with '<'; if so, use it to form an HTML pair. Eg: * <font --> <font></font> with the cursor left unchanged (ie. at the * first '>'). * only takes the word from before the cursor. * always uses insert mode. * 050908: fix cursor position due to scrolling. */static int test_for_html( TDE_WIN *window ){LANGUAGE *language;line_list_ptr line;text_ptr text;int len;text_t buf[MAX_LINE_LENGTH];int rcol, ccol;int pos;int ins;int rc = ERROR; language = window->file_info->syntax; if (language == NULL) return( ERROR ); do { /* no need for my_strcmp, since "html" is English */ if (stricmp( language->name, "html" ) == 0) break; language = language->parent; } while (language != NULL); if (language == NULL) return( ERROR ); rcol = window->rcol; if (g_status.copied) { text = g_status.line_buff; len = g_status.line_buff_len; } else { line = window->ll; text = line->line; len = line->len; } if (window->file_info->inflate_tabs) rcol = entab_adjust_rcol( text, len, rcol, window->file_info->ptab_size ); if (len >= 2 && rcol >= 2 && rcol <= len) { len = 0; while (--rcol > 0 && myisnotwhitespc( text[rcol] )) ++len; if (text[rcol] == '<' && len > 0) { buf[0] = '>'; buf[1] = '<'; buf[2] = '/'; pos = 3; do buf[pos++] = text[++rcol]; while (--len != 0); buf[pos++] = '>'; buf[pos] = '\0'; rcol = window->rcol; ccol = window->ccol; ins = mode.insert; mode.insert = TRUE; rc = add_chars( buf, window ); mode.insert = ins; check_virtual_col( window, rcol, ccol ); } else rc = ERROR; } return( rc );}static BLOCK block;/* * Name: play_back * Purpose: play back a series of keystrokes assigned to key * Date: April 1, 1992 * Modified: November 13, 1993, Frank Davis per Byrial Jensen * Notes: go thru the macro key list playing back the recorded keystrokes. * to let macros call other macros, we have to 1) save the next * keystroke of the current macro in a stack, 2) execute the * the called macro, 3) pop the key that saved by the calling * macro, 4) continue executing the macro, beginning with the * key we just popped. * use a stack to store keys. * Rewritten by Jason Hood, July 18, 1998. * jmh 980726: with the repeat function, this function needs to return * an appropriate status. * jmh 990214: recognize the break-point for recursive macros (why wasn't it * already done??) * jmh 990410: changed (rc == OK) conditions to (rc != ERROR) since not all * functions return OK (such as set_*_margin() ). * jmh 991027: corrected a bug where using a macro to play a macro twice * would result in a false recursive macro. * jmh 010601: special case for pseudo-macros and HTML. * jmh 021210: have recursive macros return OK (so other macros can call them). * jmh 050709: test for valid block type. */int play_back( TDE_WIN *window ){int rc = OK;int popped; /* flag is set when macro is popped */MACRO *mac = NULL;int cur_mode[3]; /* remember the current editor settings */unsigned pkey = 0;MACRO *pmac = NULL;MACRO_STACK ms;MACRO_STACK *old_ms = NULL;int html = FALSE; /* are we using the HTML language? */file_infos *file;int recursed; if (g_status.macro_executing) { /* * jmh 021024: It is possible for the startup macro to recurse * (typically by ending it with File); if that is the case, * restart it and let the current play_back() execute it. */ if (g_status.current_macro == macro[KEY_IDX( _CONTROL_BREAK )]) { g_status.macro_next = 0; return( ERROR ); } old_ms = g_status.mstack; g_status.mstack = NULL; } ms.macro = g_status.current_macro; /* these are part of the above if */ ms.pos = g_status.macro_next; /* but moved outside to avoid GCC */ ms.mark = g_status.macro_mark; /* uninitialised warnings */ /* * Determine if it is a valid pseudo-macro. * If so, set the key pressed to the combination. * If not, and we're recording, forget the key. */ if (g_status.command == PseudoMacro) { if ((pkey = find_combination( window )) == 0 || (pmac = find_pseudomacro( pkey, window )) == NULL) { rc = test_for_html( window ); if (rc == OK) html = TRUE; else if (mode.record == TRUE) show_avail_strokes( +1 ); } else { g_status.key_pressed = pkey; g_status.key_macro = pmac; } } /* * if we are recording a macro, let's just return if we do a recursive * definition. Otherwise, we end up executing our recursive macro * while we are defining it. * jmh 980722: may as well stop recording altogether. */ if (mode.record == TRUE && g_status.key_pressed == g_status.recording_key) { record_on_off( window ); rc = ERROR; } if (rc == OK && !html && (g_status.key_macro->flag & NEEDBLOCK)) { const char *errmsg = NULL; if (g_status.marked) { int type; switch (g_status.marked_file->block_type) { case BOX: type = NEEDBOX; break; case LINE: type = NEEDLINE; break; case STREAM: type = NEEDSTREAM; break; default: type = 0; assert( FALSE ); } if (!(type & g_status.key_macro->flag)) errmsg = main18; } else errmsg = main17; if (errmsg) { error( WARNING, window->bottom_line, errmsg ); rc = ERROR; } } if (rc == OK && !html) { cur_mode[0] = mode.insert; cur_mode[1] = mode.smart_tab; cur_mode[2] = mode.indent; file = window->file_info; /* * set the global macro flags, so other routines will know * if a macro is executing. * initialize the popped flag to FALSE being that we haven't * popped any thing off the stack, yet. */ g_status.macro_executing = TRUE; popped = FALSE; rc = OK; while (rc != ERROR) { /* * the first time thru the loop, popped is FALSE. */ if (popped == FALSE) { /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -