Home
Downloads
Media
Blog Roll
Contact

 

 

Executable Plug-In Tutorial

 

Introduction

 

An Executable Plug-In retrieves TEdit's information (such as current cursor position, etc.) through PPI function/procedure calls. A list of PPI calls can be found at the Help menu. PPI calls follow the same format as Tcl function calls, that is, a function name followed by the arguments (if any), separated only by spaces. For example, a call to function foo with arguments bar and quux looks like this:

 

foo bar quux

 

An Executable Plug-In is always executed on TEdit starts up, with no command line argument passed to it. That is the time when it initializes, such as adding a menu item to the plug-in menu (by making the tedit::ppi::addmenuitem), and register itself to be called back when the menu item is selected, etc.

 

An Executable Plug-In makes a PPI call in these 3 steps:

  1. send the PPI call as a string to STDOUT, with an eol (end of line character) appended at the end. There can only be one eol in the entire string.
  2. read a line (including the eol) from STDIN. The read in string is the text representation of the length (in number of characters) of the return value that follows.
  3. read in the return value from STDIN.

 

An Executable Plug-In must send the string "bye" (appended with an eol) to TEdit before it exits.

 


C/C Support

 

A C/C header file, teditppi.h, is located at TEdit/plugin directory. Three macros are defined to simplify PPI calling:

 

TEDITPPIPROCCALL(call)
This macro is used to make PPI procedure calls (ignore return values) to TEdit.
call is a char* pointing to the PPI call string.

 

TEDITPPIFUNCCALL(call, retptr)
This macro is used to make PPI function calls to TEDIT.
call is a char* pointing to the PPI call string.This macro is used to make PPI function calls to TEDIT.
retptr is a char* pointer. On return, retptr points to a heap allocated buffer that contains the return value of the PPI call. User must free the buffer space when it is no longer needed.

 

TEDITPPIENDSESSION()
This macro sends the "bye" string to TEdit. It should be called right before an Plug-In Executable exits.

 

Print Plug-In Example

 

Let's consider an application in which the highlighted text in TEdit is sent to the printer. The plug-in needs to get the indices (positions) of the start and end of the highlighted portion. Then it needs to get the text within those indices, and sends it to the printer:

 

extern void send_to_printer(char*);
void print() {
  char* retptr;
  char callbuf[128];
  /* get highlighted portion's begin and end indices */
  TEDITPPIFUNCCALL("tedit::ppi::gethighlighted", retptr);
  /* append the begin and end indices to the gettextat */
  /* ppi call as arguments */
  sprintf(callbuf, "tedit::ppi::gettextat %s", retptr);
  free(retptr);
  /* get highlighted text, store at buffer */
  TEDITPPIFUNCCALL(callbuf, retptr);
  send_to_printer(retptr);
  free(retptr);
}
 

 

The Executable Plug-In also needs to register itself as a callback on TEdit's start up, which is when it is first executed:

 

#define PRINT 1
/* self is the full path name to itself */
void registerself(char* self) {
  char callbuf[128];
  /* add this plug-in to the plug-in menu and */
  /* register itself as a callback, and called with the PRINT */
  /* argument when called back. */
  sprintf(callbuf, "tedit::ppi::addmenuitem \"print\" "
          "command tedit::ppi::pluginexec %s %d"
,
          self, PRINT);
  TEDITPPIPROCCALL(callbuf);
}

 

Now when the executable is first executed (with no argument) on TEdit's starts up, it registers itself as callback. Then later when it is called back (with the PRINT command line argument), it prints the highlighted protion of text:

 

#include "teditppi.h"
int main(int argc, char* argv[]) {
  if (argc == 1) {
    /* command line argument not exists, must be */
    /* the initial call */

    registerself(dostounixpath(argv[0]));
  } else {
    /* command line argument exists, must be a callback */
    if (argc == 2 && atoi(argv[1]) == PRINT) {
      print();
    }
  }
 
  /* send bye */
  TEDITPPIENDSESSION();
  return 0;
}

 

Note that TEdit uses Unix path convention (slahes instead of backslashes). Hence, Windows executable's path must first be converted:

 

char* dostounixpath(char* path) {
  int i;
  int len = strlen(path);
  for (i = 0; i < len; i ) {
    if (path[i] == '\\') {
      path[i] = '/';
    }
  }
  return path;
}

 

By naming the compiled executable with a .exe extension, and put it in the plugin subdirectory of TEdit, a menu selection called "Print" will appear in the Plug-In menu item.