TCC plugins are user-written DLL's that allow you to write your own internal variables, variable functions, and internal commands, and have TCC load them at startup. Plugin names will override existing names, so you can extend and/or replace internal variables and commands. When TCC starts, it will automatically load any plugins in the default directory (the subdirectory PLUGINS\ in the TCC installation directory). The plugins will be loaded before the startup file (TCSTART) are executed.

 

You can specify a particular plugin to execute by prefixing the function / variable / command name with the plugin name and a $. For example:

 

echo %_myplugin$variable

echo %@myplugin$func[abc]

myplugin$mycommand

 

Plugins can be written in any language that can create a Windows DLL. The TCC plugin SDK has samples for Visual C++ and Delphi. The SDK is available on our web site at https://jpsoft.com/downloads/sdk/sdk.zip.

 

Keystroke Plugins:

 

You can also write keystroke plugins that will be called for every keystroke entered at the command line. A keystroke plugin can perform actions when a specific key is entered, or even change the key before passing it back to the command processor. Keystroke plugins are called after key aliases, and before TCC looks for the default action for that key.

 

V24+ only: If the value passed in "nKey" is 0, the key is not a valid Unicode character, and the plugin needs to parse the pszKey string to get the name. The name will be passed in the format:

 

[Ctrl-][Alt-][Shift-]key

 

For example:

 

F12

Ctrl-F1

Ctrl-Alt-Left

Ctrl-Shift-F5

 

The keystroke plugin can modify the nKey or pszKey value and pass it back to TCC to evaluate the default action for the (new) value. If nKey is != 0, TCC will treat it as a normal Unicode character. If nKey = 0, TCC will evaluate pszKey for a valid keyname.

 

If the plugin handled the key and doesn't want TCC to do anything more, set nKey to 0 and pszKey to an empty string (write a null to the first byte).

 

Plugin Syntax:

 

// PluginInfo structure - returned by plugin in response to GetPluginInfo() call from command processor

// Note that the strings should all be Unicode; if your PlugIn is compiled for ASCII you'll need to use

//   the MultiByteToWideChar API to convert the strings before passing them back to TCC

typedef struct {

 TCHAR        *pszDll;        // name of the DLL

 TCHAR        *pszAuthor;        // author's name

 TCHAR        *pszEmail;        // author's email

 TCHAR        *pszWWW;        // author's web page

 TCHAR        *pszDescription;        // (brief) description of plugin

 TCHAR        *pszFunctions;        // comma-delimited list of functions in the

                 //   plugin (leading _ for internal vars, @ for

                 //   var funcs, * for keystroke function,

                 //   otherwise it's a command)

 int        nMajor;        // plugin's major version #

 int        nMinor;        // plugin's minor version #

 int        nBuild;        // plugin's build #

 HMODULE        hModule;        // module handle

 TCHAR        *pszModule;        // module name

} PLUGININFO, *LPPLUGININFO;

 

 

// structure passed to plugin functions to monitor keystrokes. A

//   keystroke function can be named anything, but must prefix a

//   * to its name in the function list (pszFunctions, above).

//   If the keystroke plugin handled the keystroke and doesn't want

//   to pass it back to TCC, it should set nKey = 0 and pszKey to an empty string.

//   The command processor will call the keystroke function with all

//     parameters set to 0 just before accepting input for each new

//     command line.

//   The string pointers are Unicode

typedef struct {

 int        nKey;        // key entered

 int        nHomeRow;        // start row

 int        nHomeColumn;        // start column

 int        nRow;        // current row in window

 int        nColumn;        // current column in window

 LPTSTR        pszLine;        // command line

 LPTSTR        pszCurrent;        // pointer to position in line

 int        fRedraw;        // if != 0, redraw the line

 LPTSTR        pszKey;        // (v24+ only) ASCII name of key (for example, "Ctrl-Alt-Home")

} KEYINFO, *LPKEYINFO;

 

__declspec(dllexport) BOOL WINAPI InitializePlugin( void );        // called by command processor after loading all plugins

__declspec(dllexport) LPPLUGININFO WINAPI GetPluginInfo( HMODULE hModule );        // called by command processor to get information from plugin, primarily for the names of functions & commands

__declspec(dllexport) BOOL WINAPI ShutdownPlugin( BOOL bEndProcess );        // called by command processor when shutting down

 //   if bEndProcess = 0, only the plugin is being closed

 //   if bEndProcess = 1, the command processor is shutting down

 

The functions listed in "pszFunctions" and called by TCC need to be in the format:

 

DLLExports INT WINAPI MyFunctionName( LPTSTR pszArguments );

 

Internal variable names in pszFunctions (and their corresponding functions) must begin with an underscore ('_').

 

Variable function names in pszFunctions must begin with an @; the corresponding function must be prefixed by "f_". (This allows variable functions to have the same name as internal commands.)

 

For example:

 

 pszFunctions = "reverse,@reverse"

 

 Entering the name "reverse" on the command line will invoke the command reverse()

 Entering the name "@reverse[]" on the command line will invoke the variable function f_reverse()

 

Variable function names are limited to a maximum of 31 characters.

 

Internal command names are any combination of alphanumeric characters (maximum 12 characters).

 

Calling the PlugIn:

 

For internal variables, pszArguments is empty (for output only)

 

For variable functions, pszArguments passes the argument(s) to the plugin function

 

For internal commands, pszArguments is the command line minus the name of the internal command

 

Returning from the PlugIn:

 

For internal variables and variable functions, copy the result string over pszArguments. The maximum string length for internal variables and variable functions is 32K (32767 characters + terminating null character).

 

Internal variables have no meaningful integer return value. For variable functions, the integer return can be:

 

 0 = success

 < 0 = failure; error message already displayed by the PlugIn function

 > 0 = failure; error value should be interpreted as a system error and

                 displayed by 4NT / TC

 

There is a special return value (0xFEDCBA98) that tells the parser to assume that the plugin decided not to handle the variable/function/command. The parser then continues looking for a matching internal, then external. Note that you can use this return value to have your plugin modify the command line and then pass it on to an existing internal variable/function/command!

 

For internal commands, return the integer result (anything left in pszArgument will be ignored)

 

Exception Handling:

 

TCC will trap any exceptions occurring in the plugin, to prevent the plugin from crashing the command processor. An error message will be displayed and the plugin will return an exit code = 2.

 

Filename Completion

 

When TCC is performing filename ("tab") completion, it will look for a plugin function named TABCOMPLETION. Like TABCOMPLETE scripts, TABCOMPLETION allows you to create plugin functions to customize TCC's filename completion. The syntax is:

 

INT WINAPI TABCOMPLETION(LPCTSTR CommandLPCTSTR Argumentint IndexLPCTSTR CommandLine);

 

Command - the name of the command at the beginning of the command line

 

Argument - the current argument being evaluated

 

Index - the offset in the command line of the beginning of Argument

 

CommandLine - the entire command line (double quoted)

 

When the plugin function finishes, it should return 0 if it processed the completion, and save the result(s) in the TABCOMPLETIONRESULT environment variable. If the function has multiple completion results, they should be added to TABCOMPLETIONRESULT, separated by a space (and double quoted if they contain any whitespace).

 

TCC will examine the contents of TABCOMPLETIONRESULT; if it contains a single value TCC will insert it at the completion point on the command line. If there are multiple return values, TCC will display a popup window for selection (like the F7 completion window).

 

TCC will try to find a filename completion script first; if none of them perform the requested completion, TCC will look for the plugin function.

 

You can specify a particular plugin to execute by prefixing the function / variable / command name with the plugin name and a $. For example:

 

echo %_myplugin$variable

echo %@myplugin$func[abc]

myplugin$mycommand