TIPS FOR PORTING YOUR FILTERMEISTER CODE

Please note! This is a work in progress / very alpha version of this document. It might not answer all your questions, and might not even be updated to the latest version of FilterMeister VS. If you have questions, please ask on the FMML FilterMeister Mailing List [1]. Information here could be incorrect, but hopefully it is still helpful.

A QUICK OVERVIEW

Before we jump into how to port your code, lets take a look at the new basic code template for a FilterMeister VS plug-in:

	#define plugInName "Filter For Testing"
	#define plugInVendorName "My Company" // Also the plugin category
	#define plugInVersion "1.00"

	#include "components/filtermeister/FW_CTL_to_C.h"
	CtlDef { return true; }
	AboutMessage {}

	#include "components/filtermeister/FW_FFP_to_C.h"

	OnCtl(n) { return true; }
	OnFilterStart { return true; }
	ForEveryTile { return true; }
	OnFilterEnd { return true; }
	OnFilterExit { return true; }

The placement of those include lines is very important. FW_CTL_to_C.h must go before CtlDef, as it provides a list of functions that are used to create the controls. FW_FFP_to_C.h must go before all other handlers, as it provides the functions that make up the FilterMeister language that you are used to. Some functions work differently in CtlDef compared to the other Handlers, and that is why the order and placement of the includes is so important.

Now we'll go through step-by-step how to port your older FilterMeister Classic code into a FilterMeister VS C++ file.

REMOVE THE % LANGUAGE IDENTIFIERS

First, delete the %FML or %FFP from the start of your code (and %EOF at the end of your file, if you use that). Those are not needed in FilterMeister VS and aren't compatible with C++.

FIXING THE HANDLERS

Handlers no longer use colons, so next, be sure to change:

  OnCtl(n):      -> OnCtl(n)
  OnFilterStart: -> OnFilterStart
  ForEveryTile:  -> ForEveryTile
  OnFilterEnd:   -> OnFilterEnd

There are some new Handlers you need to add. CtlDef is used to define the dialog controls (ie where you might currently have ctl[CTL_OK], ctl[CTL_CANCEL] and other similar definitions). So wrap these definitions with a CtlDef handler, and add the include line for CTL definitions, like this:

    #include "components/filtermeister/FW_CTL_to_C.h"
	CtlDef {
		ctl(CTL_OK) blah blah
		ctl(CTL_CANCEL) blah blah
	}

Next, you need to add an AboutMessage handler, that just returns the text for your about screen. So add this after your CtlDef block:

	AboutMessage { return "My about screen message goes here."; }

Next, you need to add the include file for all the FilterMeister functions. This has to go next, because it slightly changes the way some of the functions worked in the CtlDef section, so that they work correctly for your filter code. So add this line next

	#include "components/filtermeister/FW_FFP_to_C.h"

Lastly, there is a new OnFilterExit handler that you need to add for your code to compile. This gets called when the filter is unloaded, you might use it to free up memory. So add this line at the end of your code:

   OnFilterExit { return; }

FIXING THE INTRO PART

Lets go back to the start of your plugin file now. You probably have some definitions at the top of your file that look like this:

	Title:        "Plaid Lite"
	Organization: "namesuppressed"
	Version:      "1.00"
	About:        "Plaid Lite v1.0 for Windows"

These change to these now:

	Title:			becomes		#define plugInName
	Organization:	becomes		#define plugInVendorName
	Version:		becomes		#define plugInVersion
	SupportedModes: becomes		#define plugInSupportedModes
	FilterCaseInfo:	becomes		#define plugInEnableInfo
	About:			becomes		AboutMessage { return ""; }

So our example now looks like this:

	#define plugInName "Plaid Lite"
	#define plugInVendorName "namesuppressed"
	#define plugInVersion "1.00"
	AboutMessage { return "Plaid Lite v1.0 for Windows"; }

These functions are no longer used:

	Filename:	is no longer used.
	About:		is moved into the AboutMessage handler.
	Category:		becomes		....
	Author:			becomes		....
	URL:			becomes		....
	Copyright:		becomes		....
	Description:	becomes		....

Note that there are changes to SupportedModes and plugInEnableInfo too.

FIXING THE DIALOG DEFINITION

Dialog definitions are moved into the CtlDef handler.

	Dialog: Text =		becomes		dialogtext()
	Dialog: NoTitleBar	becomes		notitlebar
	Dialog: Size =		becomes		dialogsize(x,y)
	Dialog: Bitmap =	becomes		dialogimage("")
	Dialog : Drag = Background becomes dragbackground
	Dialog: Bitmap = "", stretched becomes setDialogImageMode(DIM_STRETCHED,0);

These are no longer supported:

	Dialog: initevent		(use OnWindowStart instead?)
	Dialog: cancelevent		(use OnFilterExit instead)
	Dialog: keyevents

HOW TO TRANSLATE EACH CONTROL

Lets start with an example, then we'll explain the theory behind it:

	ctl[CTL_UNLOCKTEXT2] : STATICTEXT(left, mouseover, notify), Invisible,
			Text = "Testing!", Pos = (385, 87), Size = (94, 20),
			FontColor = RGB(255, 255, 255)

Now becomes:

	ctl(CTL_UNLOCKTEXT2) statictext() left() mouseover() notify()
			invisible() text("Testing!") pos(385,87) size(94,20)
			fontcolor(RGB(255,255,255))

First, note that the square brackets around the control number (after ctl) now become the regular rounded brackets. The colon disappears as well. ctl now works as a function, not an array, in FilterMeisterVS.

Control Classes aren't used anymore. They were the part in capital letters that defined what type of control it was. These are now functions that are called before other modifiers. For example:

	STANDARD(horz)     becomes   standard()
	STANDARD(vert)     becomes   standardvert()
	PUSHBUTTON         becomes   pushbutton()
	BITMAP             becomes   bitmap()
	COMBOBOX           becomes   combobox()
	EDIT               becomes   edit()
	STATICTEXT         becomes   statictext()
	CHECKBOX           becomes   checkbox()

There are a handful of slightly less obvious conversions:

	IMAGE              becomes   imagectl()
	NONE               becomes   invisible()

Control modifiers are now separate functions, not part of the control class definition. So this code:

	STATICTEXT(left, mouseover, notify)

now becomes:

	statictext() left() mouseover() notify()

However, horz and vert are not used anymore. You'll need to use separate functions to create horizontal or vertical sliders:

    standard()      // Horizontal slider
    standardvert()  // Vertical slider

MODIFY is no longer used.

Action is now a function that is all one word. For example:

	Action = PREVIEW   becomes   actionpreview()
	Action = NONE      becomes   actionnone()
	Action = APPLY     becomes   actionapply()
	Action = CANCEL    becomes   actioncancel()
	Action = ABOUT     becomes   actionabout()

Pos, Size, Val and Range remain the same, except they are lowercase and you must drop the equals sign. So:

	Pos = (476, 325)   becomes   pos(476,325)
	Size = (50, 12)    becomes   size(50,12)
	Val = 0            becomes   val(0)
	Range = (1, 400)   becomes   range(1,400)

Note that you can't use * modifiers here (eg Size(50,*)), these should be replaced by -1 instead.

Text is a function too, so remove the equals sign & use brackets:

	Text = "OK"        becomes   text("OK")

And also for tooltips:

	Tooltip = "Visit site" becomes   tooltip("Visit site")

You can find the full list of these in the FW_CTL_to_C.h file.

USING T-BUFFERS

If your plugin uses the t-buffers (that is, you use any of the functions like tset, tget, t2set, t2get etc), then you need to setup support for those buffers in the CtlDef part of your code. Before any other code, include these lines:

	need_tbuf = true;
	need_t2buf = true;
	need_t3buf = true;
	need_t4buf = true;

If you don't need a particular buffer (maybe you don't use t4 buffers in your code), you can set it to false or delete that line. This will help conserve memory for your users.

POINTER CHANGES IN C

In FilterMeister Classic, everything was just a pointer, not necessarily a pointer to a char or to an int. But in C, you need to be more explicit in what you want to do, by using casts. So if you have code like this in FilterMeister:

  char *filename = calloc(256, 1);

then notice that calloc creates a "void" pointer. That is, it can be anything, and it doesn't know specifically what it is yet. Visual Studio will warn you about this. In this case, you need to cast it to be a pointer to a string of characters (chars), like this:

  char *filename = (char *)calloc(256,1);

Similarly, you can't use FilterMeister's usual void pointers with file functions, like fopen, fseek, fclose. So if you've made a pointer to a file like this in FilterMeister:

	void *DATA_FILE;
	DATA_FILE = fopen(str9, "rb+");

then you need to make it specifically a FILE pointer in FilterMeisterVS:

	FILE *DATE_FILE;
	DATA_FILE = fopen(str9, "rb+");

SUPPORTED MODES AND ENABLE INFO

#define plugInSupportedModes noBitmap, noGrayScale, noIndexedColor, doesSupportRGBColor, noCMYKColor, noHSLColor, noHSBColor, noMultichannel, noDuotone, noLABColor

#define plugInEnableInfo "in (PSHOP_ImageMode, RGBMode, RGB48Mode) || PSHOP_ImageDepth == 16"

RESOURCES / BITMAPS

Edit FilterResources.rc in the Plugin Code / Resources folder of the project. To get to the code text in Visual Studio, right-click on it and choose View Code.

IDB_BITMAP4             BITMAP	"resources\\bitmaps\\aboutscreen-plaidlite2.bmp"
//IDB_BITMAP4             BITMAP  DISCARDABLE     "resources\\fmvs_logo.bmp"

// Note: You don't actually need any of the DISCARDABLE, FIXED, IMPURE parts.
// They are all ignored on Windows versions that are not 16-bit.
// All you need is this format:		nameID	BITMAP	filename
// Or for wave files:				nameID	WAVE	filename

bitmaps\background.bmp  	BITMAP  "resources\\bitmaps\\background.bmp"
bitmaps\cart_32x32.bmp		BITMAP	"resources\\bitmaps\\cart_32x32.bmp"
bitmaps\ulock_32x32.bmp		BITMAP	"resources\\bitmaps\\ulock_32x32.bmp"
sounds\thankyou.wav			WAVE	"resources\\sounds\\thankyou.wav"

You might see some definitions like FIXED, IMPURE, DISCARDABLE. You can actually delete those, they only apply in Windows 3.1 and not to any 32-bit or 64-bit versions of Windows.

IDB_BITMAP4 is the About Screen image, so do not change its nameID.