📄 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.
*
* 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
*
* 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"
/*
* keystroke record functions
*/
/*
* 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: record_keys
* Purpose: save keystrokes in keystroke buffer
* Date: April 1, 1992
* Passed: line: line to display prompts
* Notes: -1 in .next field indicates the end of a recording
* STROKE_LIMIT+1 in .next field indicates an unused space.
*/
void record_keys( int line )
{
register int next;
register int prev;
int key;
int func;
if (mode.record == TRUE) {
if (g_status.stroke_count == 0)
/*
* no more room in recording buffer
*/
error( WARNING, line, main13 );
else {
key = g_status.key_pressed;
func = getfunc( key );
if (func != RecordMacro && func != SaveMacro && func != LoadMacro &&
func != ClearAllMacros) {
/*
* a -1 in the next field marks the end of the keystroke recording.
*/
next = macro.first_stroke[g_status.recording_key - 256];
if (macro.strokes[next].next != STROKE_LIMIT+1) {
while (macro.strokes[next].next != -1)
next = macro.strokes[next].next;
}
prev = next;
/*
* now find an open space to record the current key.
*/
if (macro.strokes[next].key != -1) {
for (; next < STROKE_LIMIT &&
macro.strokes[next].next != STROKE_LIMIT+1;)
next++;
if (next == STROKE_LIMIT) {
for (next=0; next < prev &&
macro.strokes[next].next != STROKE_LIMIT+1;)
next++;
}
}
if (next == prev && macro.strokes[prev].key != -1)
/*
* no more room in recording buffer
*/
error( WARNING, line, main13 );
else {
/*
* next == prev if we are recording the initial macro node.
*/
macro.strokes[prev].next = next;
macro.strokes[next].next = -1;
macro.strokes[next].key = key;
g_status.stroke_count--;
show_avail_strokes( );
}
}
}
}
}
/*
* Name: show_avail_strokes
* Purpose: show available free key strokes in lite bar at bottom of screen
* Date: April 1, 1992
*/
void show_avail_strokes( void )
{
char strokes[MAX_COLS];
s_output( main18, g_display.mode_line, 33, g_display.mode_color );
itoa( g_status.stroke_count, strokes, 10 );
s_output( " ", g_display.mode_line, 51, g_display.mode_color );
s_output( strokes, g_display.mode_line, 51, g_display.mode_color );
}
/*
* 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: load_strokes
* Purpose: load strokes from a file
* Date: April 1, 1992
* Passed: window: pointer to current window
* Notes: show the user a file pick list. I can never remember macro
* file names or the directory in which they hide. might as well
* give the user a file pick list.
*/
int load_strokes( WINDOW *window )
{
register FILE *fp; /* file to be read */
char dname[MAX_COLS]; /* directory search pattern */
char stem[MAX_COLS]; /* directory stem */
register int rc;
dname[0] = '\0';
/*
* search path for macro file
*/
if (get_name( main21, window->bottom_line, dname,
g_display.message_color ) == OK && *dname != '\0') {
if (validate_path( dname, stem ) == OK) {
rc = list_and_pick( dname, stem, window );
/*
* if everything is everything, load in the file selected by user.
*/
if (rc == OK) {
if ((fp = fopen( dname, "rb" )) != NULL && ceh.flag != ERROR) {
fwrite( ¯o.first_stroke[0], sizeof(int), MAX_KEYS, fp );
fwrite( ¯o.strokes[0], sizeof(STROKES), STROKE_LIMIT, fp );
fclose( fp );
}
if (ceh.flag == OK)
connect_macros( );
}
} else
/*
* invalid path or file name
*/
error( WARNING, window->bottom_line, main22 );
}
return( OK );
}
/*
* Name: clear_macro
* 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.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -