Plug-In API Questions

vladsch

Member²
I am writing a plug-in to allow me to switch between plsql dev and my editor seamlessly. This means being able to synchronize cursor position information between the two. BTW, I am running 7.0.3 beta.

1. I ran into a snag when a package is opened as Spec&Body. The API (IDE_TabInfo() IDE_TabIndex()) reports no tabs for the window.

Is there way to query and select spec or body tabs so that I can get/set the cursor position for each tab and to select the active tab?

Since both are saved to the same file the cursor line information for the body needs to be offset by the number of lines in the spec.

2. I would also like my plug-in to disable the automatic file change detection (when disk file changes) and the corresponding nag message box. Is there an easier way to do this short of window message hooks and monitoring when the message box pops up so that it is dismissed from code?

The reason I want to disable it is because it does not work consistently except for program windows. SQL windows only detect change when they were not modified and (I am not sure about this but almost certain) when the query was not executed.

My plug-in will take care of this and also have automatic file reload when change is detected as an option so there is no nagging.

3. I noticed that the RegisterCallback() function is called with a few undocumented ID's, (these were there in 7.0.2 also):

RegisterCallback(9, 00AD9D24)
RegisterCallback(109, 00ADCAA4)
RegisterCallback(133, 00ADD794)
RegisterCallback(134, 00ADD7FC)
RegisterCallback(135, 00ADD898)
RegisterCallback(170, 00ADDE20)
RegisterCallback(171, 00ADDE28)
RegisterCallback(172, 00ADDE30)
RegisterCallback(176, 00ADE06C)
RegisterCallback(231, 00ADF89C)

Does anyone know what these functions are? The reason I ask is that some of these may solve my problem(s).
 
1. IDE_TabInfo seems to work okay. At which point do you make the call? (OnCreate, ...)

2. We will look into this and try to let all windows behave consistant. We will also look into an option to let a Plug-In overrule file change detection.
 
Marco,

I did not clue in until your question: yes, I was calling TabInfo from OnWindowCreate(). Changed it to OnWindowChange() and all works great.

Thank you very much.
 
Marco,

Next snag: how do I get default extension for a program window? The IDE_GetDefaultExtension() takes a window type, but program windows have many extensions and windowtype integer is not sufficient to differentiate them.

I am trying to get a default extension for a program window that has not been saved yet, the program type is known but there is no file name.

The IDE_GetWindowObject() reports the correct object type. So I know what type it is.

How can I get the extensions that are configured in the Preferences/File/Extensions dialog from my plug-in?

Future enhancement: IDE_GetDefaultExtension() function should be modifed to accept a -1 for WindowType. In which case it would use the currently active window to figure out the extension. At least it will make the function useful for program windows that already exist.
 
You should be able to use function 109:
function IDE_GetProcEditExtension(oType: PChar): PChar; cdecl;
Don't know why this one isn't documented.

As type you can pass the following to get the different extensions:
FUNCTION
PROCEDURE
TRIGGER
PACKAGE
PACKAGE BODY
PACKAGE SPEC AND BODY
TYPE
TYPE BODY
TYPE SPEC AND BODY
JAVA SOURCE
 
Thank you very much Marco.

It is one of the undocumented callbacks in my original post.

If someone can pass me a description of these undocumented functions I am willing to make the PL/SQL C/C++ headers available to you guys if you want to include them in the PL/SQL plug-in docs/demos.

In the headers I include ALL the documented functions with the complete description from the documentation with fixed missing indirection on 'char' arguments and return values. So the headers can be used as an alternative to documentation for C/C++ based plug-ins.

Here is an extract from the header file I use:

Code:
// Use this function to enable or disable a menu. The ID is the Plug-In ID, which is given by
// the IdentifyPlugIn function. The Index is the menu index, which the menu was related to by
// the CreateMenuItem function. The Enabled boolean determines if the menu item is enabled or
// grayed.
/*FUNC: 10*/ extern void (*IDE_MenuState)(int ID, int Index, BOOL Enabled);

// Returns a boolean that indicates if PL/SQL Developer is currently connected to a database.
/*FUNC: 11*/ extern BOOL (*IDE_Connected)();

// Returns the username, password and database of the current connection.
/*FUNC: 12*/ extern void (*IDE_GetConnectionInfo)(char **Username, char **Password, char **Database);

// Returns information about the selected item in the Browser. If no item is selected, all items are empty.
/*FUNC: 13*/ extern void (*IDE_GetBrowserInfo)(char **ObjectType, char **ObjectOwner, char **ObjectName);

// Returns the type of the current window.
// 1 = SQL Window
// 2 = Test Window
// 3 = Procedure Window
// 4 = Command Window
// 5 = Plan Window
// 6 = Report Window
// 0 = None of the above
/*FUNC: 14*/ extern int (*IDE_GetWindowType)();

// Returns the Application handle of PL/SQL Developer
/*FUNC: 15*/ extern int (*IDE_GetAppHandle)();

// Returns the handle of PL/SQL Developers main window
/*FUNC: 16*/ extern HWND (*IDE_GetWindowHandle)();
 
Sounds like a fair trade, but some functions are undocumented for a reason.

9:
function SYS_DelphiVersion: Integer;
returns the Delphi version used to build PL/SQL Developer

109:
function IDE_GetProcEditExtension(oType: PChar): PChar;
you already know.

133, 134, 135:
are related to translations, not useful for third party Plug-ins

170, 171, 172:
relate to MDI programming. When not used correct will cause instability, so we want to keep them undocumented.

176:
procedure IDE_GetBrowserFilter(Index: Integer; var Name, WhereClause, OrderByClause, User: PChar; var Active: Bool);
will return the browserfilters

231:
function IDE_CheckDBVersion(Version: PChar): Boolean;
checks if the current DB is equal or higher than then passed DB version (format '09.02' or '10.00')

that's it. We'll add these functions to the documentation as well.
 
I am updating the headers now. Do you want me to post the link to these files here?

I also checked the latest plug-in documentation and found that IDE_GetProcExtension() is documented. I was using docs from an older release that is why I did not see it. I updated the headers with function docs from the latest PDF.

As far as the other undocumented functions here is my take on it. Do not document API's that are proprietary and which you want to keep as a "trade secret". The rest should have rudimentary documentation. Any dedicated plug-in author will figure out the rest or ask for more information. Considering how many questions you field for all of the other functions I doubt that 3 extra functions will add that much more to the support load, especially when most won't bother with MDI windows.

Instability is an occupational hazard in programming and we spend a lot of time trying to find a way around it. In my plug-in I am bending over backwards trying to get functionality that I want with what is available. It takes a while to figure out how the API really works. Function calls only tell a small part of the story. When (sequence and timing) and how to use them and what side-effects they have is a trial and error endeavor. Any bit of extra information helps.

To dismiss the "Confirm" disk file changed dialog from code I added a windows hook and look for a new window being displayed with class TFormWindow and exactly two child windows of TButton class. I would like to also check that the window caption is "Confirm" and the button captions are "Yes" and "No" but that is translation language dependent so I don't do it. Maybe one of the undocumented translation related functions could give me the translated captions and prevent my code mistakenly closing a wrong dialog box.

Trial and error was needed to figure out the sequence of OnWindowCreate and OnWindowChange plug in calls. I used the C++ example which sets a flag in OnWindowCreate to mark the next call to OnWindowChange as a new window but that worked only for windows created after initialization. Any windows opened as part of workspace restoration on launch only got OnCreateWindow call followed by a single OnWindowChange for the last window. Not a problem once the behavior is known.

Regarding the IDE_SelectWindow() side-effects. In my plug-in I am assuming that after I am done I should call IDE_SelectWindow(0) to make sure that other plug-ins are not affected. Another plug-in may just call other IDE_... window functions without a call to SelectWindow(0) because it needs to deal only with the currently active window. In which case not resetting IDE_SelectWindow(0) will cause side-effects for that plug-in.

I suspect that these side-effects are there from other plug-ins. I have noticed focus problems and mysterious loss of caret in the current window when other things are happening in the background even without my plug-in :) .

Ideally, the window functions should have had a PlugInID argument, same as Menu/Toolbar functions. That way you could keep a per plug-in selected window index and eliminate any cross plug-in side-effects. Otherwise the IDE_SelectWindow(0) function needs to be called any time control can possibly be relinquished to another plug-in and then again with the desired index when control returns to my code.

Please let me know if I should post my header file as a link here.
 
Hello Vladimir,

Please email me the header file (thanks in advance).

I'll consider your remarks for the next release. Note there is one additional function for 7.0.3:

219:
function IDE_PlugInSetting(PlugInID: Integer; Setting, Value: PChar): Bool;
This will overrule default app behavior. Currently only the setting "NOFILEDATECHECK" is supported where you can pass "TRUE" or "FALSE".
 
Back
Top