📄 macro.c
字号:
/* * The "macro" routines in TDE are not really macro routines in the classical * sense. In TDE, "macros" are just recordings of key sequences. But, * actually, I find the ability to record and playback keystrokes generally * more useful than writing a macro. Being that I'm so stupid, it takes me * half the morning to write and half the afternoon to debug a simple classical * macro. For most of my routine, little jobs, I find it more convenient * to record my keystrokes and playback those keystrokes at appropriate places * in a file. It just seems easier for me to "teach" the editor what to do * rather than "instruct" the editor what to do. * ********************* start of Jason's comments ********************* * * Rhide has a feature called "pseudo-macros". These macros are triggered * by the two characters before the cursor. Eg: if you type in "ma" and * hit the pseudo-macro key, you could get: * * int main(int argc, char* argv[]) * { * _ * * return 0; * } * * with the cursor placed at the underscore. I've incorporated two types * of pseudo-macros in TDE: global (defined in tde.cfg) and language- * dependent (defined in tde.shl). Since these macros are created at run- * time, I've done away with the strokes buffer and allocated them from * the heap. This means that DOS must include the config file and that * macros can no longer be stored permanently. * ********************* end of Jason's comments ********************* * * New editor name: TDE, the Thomson-Davis Editor. * Author: Frank Davis * Date: June 5, 1991, version 1.0 * Date: July 29, 1991, version 1.1 * Date: October 5, 1991, version 1.2 * Date: January 20, 1992, version 1.3 * Date: February 17, 1992, version 1.4 * Date: April 1, 1992, version 1.5 * Date: June 5, 1992, version 2.0 * Date: October 31, 1992, version 2.1 * Date: April 1, 1993, version 2.2 * Date: June 5, 1993, version 3.0 * Date: August 29, 1993, version 3.1 * Date: November 13, 1993, version 3.2 * Date: June 5, 1994, version 4.0 * Date: December 5, 1998, version 5.0 (jmh) * * This modification of Douglas Thomson's code is released into the * public domain, Frank Davis. You may distribute it freely. */#include "tdestr.h" /* tde types */#include "common.h"#include "define.h"#include "tdefunc.h"#include "config.h"extern long found_rline; /* defined in findrep.c *//* * keystroke record functions *//* * Name: record_on_off * Purpose: save keystrokes in keystroke buffer * Date: April 1, 1992 * Passed: window: pointer to current window * Notes: rewritten by Jason Hood, July 17, 1998. * if the PseudoMacro key is chosen as play back, record * a pseudo-macro. * Pseudo-macros and two-keys are assumed to be recorded in * the one window (or at least the one language). * * jmh 021029: disable any previous macro mark. */int record_on_off( TDE_WIN *window ){long key;int func = 0;MACRO *mac = NULL;TREE *branch = NULL;TREE *tree;int line;char temp[MAX_COLS+2];DISPLAY_BUFF;int no_memory = FALSE;int existing = FALSE; /* pseudo-macro or two-key already exists */long *keys;int rc; tree = (window != NULL && window->syntax) ? &window->file_info->syntax->key_tree : &key_tree; mode.record = !mode.record; if (mode.record == TRUE) { line = window->bottom_line; SAVE_LINE( line ); /* * press key that will play back recording */ set_prompt( main11, line ); /* * get the candidate macro key and look up the function assigned to it. */ g_status.viewer_key = TRUE; key = getkey( ); g_status.key_macro = NULL; if (PARENT_KEY( key )) { branch = search_tree( key, tree->right ); if (branch != NULL) { existing = TRUE; func = branch->func; g_status.key_macro = branch->macro; } } else func = getfunc( key ); if (key == ESC || func == AbortCommand || key == _CONTROL_BREAK) mode.record = FALSE; /* * the key must be an unused, recognized function key or a function * key assigned to a previously defined macro. */ else if (key <= 256 || (func != 0 && func != PlayBack && func != PseudoMacro)) { /* * cannot assign a recording to this key */ join_strings( temp, main12, main12a ); error( WARNING, line, temp ); mode.record = FALSE; } if (mode.record == TRUE && func == PseudoMacro) { key = find_combination( window ); if (key == 0) { /* * cannot assign a recording to this combination */ join_strings( temp, main12, main12b ); error( WARNING, line, temp ); mode.record = FALSE; } else { branch = search_tree( key, tree->left ); if (branch != NULL) { existing = TRUE; g_status.key_macro = branch->macro; } } } if (mode.record == TRUE) { /* * check for a previous macro */ if ((mac = g_status.key_macro) != NULL) { /* * overwrite recording? */ if (get_yn( main14, line, R_PROMPT | R_ABORT ) != A_YES) mode.record = FALSE; } } if (mode.record == TRUE) { if (mac != NULL) { /* * key has already been assigned to a macro, clear macro def. */ if (mac->len > 1) my_free( mac->key.keys ); mac->len = 0; } else { if ((func == PseudoMacro || PARENT_KEY( key )) && !existing) { if ((branch = my_calloc( sizeof(TREE) )) == NULL) { mode.record = FALSE; no_memory = TRUE; } } if (mode.record == TRUE) { if ((mac = my_calloc( sizeof(MACRO) )) == NULL) { mode.record = FALSE; no_memory = TRUE; } } } } if (mode.record == TRUE) { /* * Try allocating STROKE_LIMIT first. If it fails, halve * it each time and try again. */ g_status.stroke_count = STROKE_LIMIT; while ((mac->key.keys = my_malloc( g_status.stroke_count * sizeof(long), &rc )) == NULL && g_status.stroke_count > 1) g_status.stroke_count /= 2; if (mac->key.keys == NULL) { mode.record = FALSE; no_memory = TRUE; } } if (mode.record == TRUE) { g_status.recording_key = key; g_status.rec_macro = mac; mac->mode[0] = mode.insert; mac->mode[1] = mode.smart_tab; mac->mode[2] = mode.indent; g_status.macro_mark.marked = FALSE; if (func == PseudoMacro || PARENT_KEY( key )) { branch->macro = mac; if (!existing) { branch->key = key; branch->func = PlayBack; add_branch( branch, tree ); } } else { macro[KEY_IDX( key )] = mac; key_func[KEY_IDX( key )] = PlayBack; } show_recording( ); } else if (no_memory) { /* * out of memory */ error( WARNING, line, main4 ); my_free( mac ); if (!existing) my_free( branch ); } RESTORE_LINE( line ); } if (mode.record == FALSE && (mac = g_status.rec_macro) != NULL) { /* * the flashing "Recording" and the stroke count write over the modes. * when we get thru defining a macro, redisplay the modes. */ show_modes( ); /* * let's look at the macro. if no strokes were recorded, free the * macro structure; if one stroke was recorded use the pointer to * keep it; otherwise realloc to the size required. */ if (mac->len == 0) { my_free( mac->key.keys ); my_free( mac ); key = g_status.recording_key; /* * retain the branch because I really couldn't be * bothered to go to the trouble of removing it. */ if (key >= 0x2121) { branch = search_tree( key, tree ); branch->func = 0; branch->macro = NULL; } else { macro[KEY_IDX( key )] = NULL; key_func[KEY_IDX( key )] = 0; } } else if (mac->len == 1) { key = *mac->key.keys; my_free( mac->key.keys ); mac->key.key = key; } else { keys = my_realloc( mac->key.keys, mac->len * sizeof(long), &rc ); if (keys != NULL) mac->key.keys = keys; /* * Finally, move the cursor to the mark, if one was specified. */ g_status.command = MacroMark; goto_marker( window ); } g_status.recording_key = 0; g_status.rec_macro = NULL; } return( OK );}/* * Name: find_combination * Purpose: determine the two-character key for a pseudo-macro * Author: Jason Hood * Date: July 18, 1998 * Passed: window: current window * Returns: 0 for an invalid combination; * the key value otherwise. */unsigned find_combination( TDE_WIN *window ){line_list_ptr line;text_ptr text;int len;unsigned key = 0;int rcol; 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) { if (rcol >= 2 && rcol <= len && text[rcol-1] > ' ' && text[rcol-2] > ' ') key = (text[rcol-2] << 8) | text[rcol-1]; } return( key );}/* * Name: search_tree * Purpose: search a tree for a matching key * Author: Jason Hood * Date: July 29, 1998 * Passed: key: value to find * tree: tree to search * Returns: pointer to the branch if found; * NULL if not found. */TREE *search_tree( long key, TREE *tree ){ while (tree != NULL && key != tree->key) tree = (key < tree->key) ? tree->left : tree->right; return( tree );}/* * Name: find_pseudomacro * Purpose: search the trees for a matching key * Author: Jason Hood * Date: July 20, 1998 * Passed: key: pseudo-macro to find * window: current window * Returns: pointer to the macro if found; * NULL if not found. * Notes: if it can't be found in the language tree, search the global. */MACRO *find_pseudomacro( unsigned key, TDE_WIN *window ){TREE *branch;MACRO *mac = NULL;LANGUAGE *language; if (window != NULL && window->syntax) { language = window->file_info->syntax; do { branch = search_tree( key, language->key_tree.left ); if (branch != NULL) mac = branch->macro; language = language->parent; } while (mac == NULL && language != NULL); } if (mac == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -