home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / edtjava.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  45.0 KB  |  1,429 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19.  
  20. //
  21. // Java-related editor code.
  22. //
  23.  
  24. #ifdef EDITOR
  25.  
  26. #include "editor.h"
  27.  
  28. // Local header
  29. #ifdef EDITOR_JAVA
  30.  
  31. #include "java.h"
  32. #include "libi18n.h"
  33. #include "xp_file.h"
  34.  
  35. #define JRI_NO_CPLUSPLUS
  36. #ifdef XP_MAC
  37. #include "n_p_composer_PluginManager.h"
  38. #include "n_plugin_composer_Composer.h"
  39. #include "n_p_composer_MozillaCallback.h"
  40. #else
  41. #include "netscape_plugin_composer_PluginManager.h"
  42. #include "netscape_plugin_composer_Composer.h"
  43. #include "netscape_plugin_composer_MozillaCallback.h"
  44. #endif
  45.  
  46.  
  47. // This C header file doesn't have C++ linkage #ifdefs.
  48. extern "C" {
  49. #include "zip.h"
  50. };
  51.  
  52. struct netscape_plugin_composer_PluginManager;
  53. #include "jri.h"
  54.  
  55. // Interface for calling editor plugins
  56. #define PLUGIN_FAIL 0
  57. #define PLUGIN_CANCEL 1
  58. #define PLUGIN_OK 2
  59. #define PLUGIN_NEWTEXT 3
  60.  
  61. typedef void (*ComposerPluginCallbackFn)(jint, jint, struct java_lang_Object*);
  62. void EDT_ComposerPluginCallback(jint, jint, struct java_lang_Object*);
  63.  
  64. #ifdef XP_WIN16
  65. const int32 MAX_STRING=65530L;
  66. #else
  67. // const int32 MAX_STRING=500; // For testing
  68. const int32 MAX_STRING=1L<<30;
  69. #endif
  70.  
  71. class CEditorPluginInterface {
  72. public:
  73.     static XP_Bool IsValidInterface(CEditorPluginInterface* pInterface);
  74.  
  75.     CEditorPluginInterface(MWContext* pContext, ComposerPluginCallbackFn callback);
  76.     ~CEditorPluginInterface();
  77.  
  78.     static void Register(char* plugin);
  79.     static int32 GetNumberOfCategories();
  80.     static int32 GetNumberOfPlugins(int32 type);
  81.     static char* GetCategoryName(int32 type);
  82.     static char* GetPluginName(int32 type, int32 index);
  83.     static char* GetPluginHint(int32 type, int32 index);
  84.     
  85.     static int32 GetNumberOfEncoders();
  86.     static char* GetEncoderName(int32 index);
  87.     static XP_Bool GetEncoderNeedsQuantizedSource(int32 index);
  88.     static char* GetEncoderHint(int32 index);
  89.     static char* GetEncoderFileExtension(int32 index);
  90.     static char* GetEncoderFileType(int32 index);
  91.     XP_Bool StartEncoder(int32 index, int32 width, int32 height, char** pixels,
  92.         char* fileName, EDT_ImageEncoderCallbackFn doneFunction, void* doneFunctionArgument);
  93.  
  94.     XP_Bool Perform(int32 type, int32 index, EDT_ImageEncoderCallbackFn doneFunction, void* hook,netscape_javascript_JSObject *jsobject);
  95.     XP_Bool Perform(char* pClassName, EDT_ImageEncoderCallbackFn doneFunction, void* hook,netscape_javascript_JSObject *jsobject);
  96.     void Perform(char* pEvent, char* pDocURL, XP_Bool bCanChangeDocument, XP_Bool bCanCancel,
  97.         EDT_ImageEncoderCallbackFn doneFunction, void* hook,netscape_javascript_JSObject *jsobject);
  98.     XP_Bool IsPluginActive();
  99.     void StopPlugin();
  100.     void PluginCallback(int32 action, struct java_lang_Object* pArgument);
  101.     static XP_Bool PluginsExist();
  102.  
  103. protected:
  104.     struct java_lang_String* GetBaseURL();
  105.     struct java_lang_String* GetDocument();
  106.     void GetWorkDirectoryAndURL(struct java_lang_String*& workDirectory,
  107.         struct java_lang_String*& workDirectoryURL);
  108.     XP_Bool Perform2(char* pClassName, int32 type, int32 index, XP_Bool bCanChangeDocument, XP_Bool bCanCancel,
  109.         EDT_ImageEncoderCallbackFn doneFunction, void* hook, netscape_javascript_JSObject *jsobject);
  110.     void PluginFailed(struct java_lang_String* pWhy);
  111.     void PluginSucceeded();
  112.     void NewText(struct java_lang_String* pText);
  113.  
  114.     CEditBuffer* GetBuffer();
  115.  
  116. private:
  117.     void ImageEncoderFinished(EDT_ImageEncoderStatus status);
  118.     void DocumentIsTooLarge(int32 docLengthInBytes, int msgid);
  119.     static netscape_plugin_composer_PluginManager* Manager();
  120.     struct netscape_plugin_composer_Composer* Composer();
  121.     static JRIEnv* Env();
  122.     static XP_Bool g_bJavaInitialized;
  123.     static JRIEnv* g_pEnv;
  124.     static JRIGlobalRef g_pManager;
  125.     static TXP_GrowableArray_pChar g_Plugin;
  126.     static TXP_GrowableArray_CEditorPluginInterface g_Interface;
  127.     XP_Bool m_bPluginActive; // True if an image encoder or a plugin is active.
  128.     XP_Bool m_bImageEncoder; // True if we're exectuing an image encoder.
  129.     XP_Bool m_bCanChangeDocument;
  130.     XP_Bool m_bCanCancel;
  131.     XP_Bool m_bChangedDocument; // True if the current plug-in has changed the document.
  132.     JRIGlobalRef m_pComposer;
  133.     EDT_ImageEncoderCallbackFn m_doneFunction;
  134.     void* m_doneFunctionArgument;
  135.     MWContext* m_pContext;
  136.     ComposerPluginCallbackFn m_callback;
  137. };
  138.  
  139. #endif // EDITOR_JAVA
  140.  
  141.  
  142. // End of local header
  143.  
  144.  
  145. // Editor Plugin edt.h API functions.
  146.  
  147. void EDT_RegisterPlugin(char* csFileSpec){
  148. #ifdef EDITOR_JAVA
  149.     CEditorPluginInterface::Register(csFileSpec);
  150. #else
  151.     XP_TRACE(("EDT_RegisterPlugin(\"%s\")"));
  152. #endif
  153. }
  154.  
  155. int32 EDT_NumberOfPluginCategories(){
  156. #ifdef EDITOR_JAVA
  157.     if ( EditorPluginManager_PluginsExist() ) {
  158.         return CEditorPluginInterface::GetNumberOfCategories();
  159.     }
  160. #endif
  161.     return 0;
  162. }
  163.  
  164. int32 EDT_NumberOfPlugins(int32 category){
  165. #ifdef EDITOR_JAVA
  166.     if ( EditorPluginManager_PluginsExist() ) {
  167.         return CEditorPluginInterface::GetNumberOfPlugins(category);
  168.     }
  169. #endif
  170.     return 0;
  171. }
  172.  
  173. char* EDT_GetPluginCategoryName(int32 pluginIndex){
  174. #ifdef EDITOR_JAVA
  175.     if ( EditorPluginManager_PluginsExist() ) {
  176.         return CEditorPluginInterface::GetCategoryName(pluginIndex);
  177.     }
  178. #endif
  179.     return 0;
  180. }
  181.  
  182. char* EDT_GetPluginName(int32 category, int32 index){
  183. #ifdef EDITOR_JAVA
  184.     if ( EditorPluginManager_PluginsExist() ) {
  185.         return CEditorPluginInterface::GetPluginName(category, index);
  186.     }
  187. #endif
  188.     return 0;
  189. }
  190.  
  191. char* EDT_GetPluginMenuHelp(int32 category, int32 index){
  192. #ifdef EDITOR_JAVA
  193.     if ( EditorPluginManager_PluginsExist() ) {
  194.         return CEditorPluginInterface::GetPluginHint(category, index);
  195.     }
  196. #endif
  197.     return 0;
  198. }
  199.  
  200. XP_Bool EDT_PerformPlugin(MWContext *pContext, int32 category, int32 index, EDT_ImageEncoderCallbackFn doneFunction, void* hook){
  201.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  202. #ifdef EDITOR_JAVA
  203.     if ( EditorPluginManager_PluginsExist() ) {
  204.         netscape_javascript_JSObject *t_object=LJ_GetMochaWindow(pContext);
  205.         return ((CEditorPluginInterface*) pEditBuffer->GetPlugins())->Perform(category, index, doneFunction, hook, t_object);
  206.     }
  207. #endif
  208.     return FALSE;
  209. }
  210.  
  211. XP_Bool EDT_PerformPluginByClassName(MWContext *pContext, char* pClassName, EDT_ImageEncoderCallbackFn doneFunction, void* hook){
  212.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  213. #ifdef EDITOR_JAVA
  214.     if ( EditorPluginManager_PluginsExist() ) {
  215.         netscape_javascript_JSObject *t_object=LJ_GetMochaWindow(pContext);
  216.         return ((CEditorPluginInterface*) pEditBuffer->GetPlugins())->Perform(pClassName, doneFunction, hook, t_object);
  217.     }
  218. #endif
  219.     return FALSE;
  220. }
  221.  
  222. void EDT_PerformEvent(MWContext *pContext, char* pEvent, char* pDocURL, XP_Bool bCanChangeDocument, XP_Bool bCanCancel,
  223.                       EDT_ImageEncoderCallbackFn doneFunction, void* hook){
  224.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  225. #ifdef EDITOR_JAVA
  226.     if ( EditorPluginManager_PluginsExist() ) {
  227.         netscape_javascript_JSObject *t_object=LJ_GetMochaWindow(pContext);
  228.         ((CEditorPluginInterface*) pEditBuffer->GetPlugins())->Perform(pEvent, pDocURL, bCanChangeDocument, bCanCancel,
  229.             doneFunction, hook, t_object);
  230.         return;
  231.     }
  232. #endif
  233.     if ( doneFunction){
  234.         (*doneFunction)(ED_IMAGE_ENCODER_OK,  hook);
  235.     }
  236. }
  237.  
  238. XP_Bool EDT_IsPluginActive(MWContext* pContext){
  239.     GET_EDIT_BUF_OR_RETURN_READY_OR_NOT(pContext, pEditBuffer) FALSE;
  240. #ifdef EDITOR_JAVA
  241.     if ( EditorPluginManager_PluginsExist() ) {
  242.         return ((CEditorPluginInterface*) pEditBuffer->GetPlugins())->IsPluginActive();
  243.     }
  244. #endif
  245.     return FALSE;
  246. }
  247.  
  248. void EDT_StopPlugin(MWContext* pContext){
  249.     GET_EDIT_BUF_OR_RETURN_READY_OR_NOT(pContext, pEditBuffer);
  250. #ifdef EDITOR_JAVA
  251.     if ( EditorPluginManager_PluginsExist() ) {
  252.         ((CEditorPluginInterface*) pEditBuffer->GetPlugins())->StopPlugin();
  253.     }
  254. #endif
  255. }
  256.  
  257. #ifdef EDITOR_JAVA
  258. void EDT_ComposerPluginCallback(jint hook1, jint action1, struct java_lang_Object* pArg){
  259.     CEditorPluginInterface* pInterface = (CEditorPluginInterface*) hook1;
  260.     if ( ! CEditorPluginInterface::IsValidInterface(pInterface )) {
  261.         XP_ASSERT(FALSE); // A spurrious callback.
  262.         return;
  263.     }
  264.     int32 action = (int32) action1;
  265.     if ( pInterface ) {
  266.         pInterface->PluginCallback(action, pArg);
  267.     }
  268. }
  269. #endif
  270.  
  271. int32 EDT_NumberOfEncoders(){
  272. #ifdef EDITOR_JAVA
  273.     if ( EditorPluginManager_PluginsExist() ) {
  274.         return CEditorPluginInterface::GetNumberOfEncoders();
  275.     }
  276. #endif
  277.     return 0;
  278.  
  279. }
  280.  
  281. char* EDT_GetEncoderName(int32 index){
  282. #ifdef EDITOR_JAVA
  283.     if ( EditorPluginManager_PluginsExist() ) {
  284.         return CEditorPluginInterface::GetEncoderName(index);
  285.     }
  286. #endif
  287.     return 0;
  288. }
  289.  
  290. char* EDT_GetEncoderFileExtension(int32 index){
  291. #ifdef EDITOR_JAVA
  292.     if ( EditorPluginManager_PluginsExist() ) {
  293.         return CEditorPluginInterface::GetEncoderFileExtension(index);
  294.     }
  295. #endif
  296.     return 0;
  297. }
  298.  
  299. char* EDT_GetEncoderFileType(int32 index){
  300. #ifdef EDITOR_JAVA
  301.     if ( EditorPluginManager_PluginsExist() ) {
  302.         return CEditorPluginInterface::GetEncoderFileType(index);
  303.     }
  304. #endif
  305.     return 0;
  306. }
  307.  
  308. char* EDT_GetEncoderMenuHelp(int32 index){
  309. #ifdef EDITOR_JAVA
  310.     if ( EditorPluginManager_PluginsExist() ) {
  311.         return CEditorPluginInterface::GetEncoderHint(index);
  312.     }
  313. #endif
  314.     return 0;
  315. }
  316.  
  317. XP_Bool EDT_GetEncoderNeedsQuantizedSource(int32 index){
  318. #ifdef EDITOR_JAVA
  319.     if ( EditorPluginManager_PluginsExist() ) {
  320.         return CEditorPluginInterface::GetEncoderNeedsQuantizedSource(index);
  321.     }
  322. #endif
  323.     return FALSE;
  324. }
  325.  
  326.  
  327. XP_Bool EDT_StartEncoder(MWContext* pContext, int32 index, int32 width, int32 height, char** pixels,
  328.     char* csFileName, EDT_ImageEncoderCallbackFn doneFunction,
  329.     void* doneArgument){
  330. #ifdef EDITOR_JAVA
  331.     GET_EDIT_BUF_OR_RETURN_READY_OR_NOT(pContext, pEditBuffer) FALSE;
  332.     if ( EditorPluginManager_PluginsExist() ) {
  333.         return ((CEditorPluginInterface*) pEditBuffer->GetPlugins())->StartEncoder(index, width, height, pixels,
  334.             csFileName, doneFunction, doneArgument);
  335.     }
  336. #endif
  337.     return FALSE;
  338. }
  339.  
  340. void EDT_StopEncoder(MWContext* pContext){
  341. #ifdef EDITOR_JAVA
  342.     if ( EditorPluginManager_PluginsExist() ) {
  343.         EDT_StopPlugin(pContext);
  344.     }
  345. #endif
  346. }
  347.  
  348.  
  349. #ifdef EDITOR_JAVA
  350.  
  351. struct PreOpenCallbackHook {
  352.     CEditorPluginInterface* pInterface;
  353.     EDT_PreOpenCallbackFn doneFunction;
  354.     void* hook;
  355.     char* pURL;
  356. };
  357.  
  358. static void edt_SetURL(void* hook3, char* pURL){
  359.     PreOpenCallbackHook* hook2 = (PreOpenCallbackHook*) hook3;
  360.     char* pOldURL = hook2->pURL;
  361.     hook2->pURL = pURL ? XP_STRDUP(pURL) : 0;
  362.     XP_FREE(pOldURL);
  363. }
  364.  
  365. #ifndef XP_OS2
  366. static
  367. #else
  368. extern "OPTLINK"
  369. #endif
  370. void edt_PreOpenDoneFunction(EDT_ImageEncoderStatus status, void* hook3){
  371.     PreOpenCallbackHook* hook2 = (PreOpenCallbackHook*) hook3;
  372.     EDT_PreOpenCallbackFn doneFunction = hook2->doneFunction;
  373.     void* hook = hook2->hook;
  374.     char* pURL = hook2->pURL;
  375.     if ( doneFunction ) {
  376.         (*doneFunction)(status == ED_IMAGE_ENCODER_USER_CANCELED, pURL, hook);
  377.     }
  378.     CEditorPluginInterface* epi = hook2->pInterface;
  379.     if (pURL){
  380.         XP_FREE(pURL);
  381.     }
  382.     delete epi;
  383.     delete hook2;
  384. }
  385.  
  386. #endif
  387.  
  388. void EDT_PreOpen(MWContext *pErrorContext,char* _pURL, 
  389.                  EDT_PreOpenCallbackFn doneFunction, void* hook){
  390.   // Make local copy, so we can change it if we want.
  391.   char *pURL = _pURL ? XP_STRDUP(_pURL) : 0;
  392.   
  393.   // Always ignore target or query appendages
  394.   edt_StripAtHashOrQuestionMark(pURL);
  395.   
  396.   if (!pURL || !*pURL) {
  397.     // Canceled.
  398.     if (doneFunction) {
  399.       (*doneFunction)(TRUE, _pURL, hook);
  400.     }
  401.     XP_FREEIF(pURL);
  402.     return;
  403.   }
  404.  
  405.   XP_Bool bValid = FALSE;
  406.  
  407.   // Only allow editing of appropriate types of URLs.
  408.   int urlType = NET_URL_Type(pURL);
  409.   if (urlType == FILE_TYPE_URL ||
  410.       urlType == FTP_TYPE_URL ||
  411.       urlType == HTTP_TYPE_URL ||
  412.       urlType == SECURE_HTTP_TYPE_URL) {
  413.     bValid = TRUE;
  414.   }
  415.  
  416.   // Test for platform-specific filename if URL type is unknown.
  417.   if (urlType == 0) {
  418.     // don't make assumption that the user wants a local file
  419.     // If it's not a valid URL, then the user probably wants a remote file
  420.     // the following behavior is consistent with the browser location field
  421.     bValid = TRUE;
  422.   }
  423.  
  424.  
  425.   if (!bValid) {
  426.     // Don't report errors if pErrorContext is NULL.
  427.     if (pErrorContext != NULL) {
  428.       // Tell user that we are rejecting their URL.
  429.       char *tmplate = XP_GetString(XP_EDT_CANT_EDIT_URL);
  430.       char *msg = NULL;
  431.       if (tmplate) {
  432.         msg = PR_smprintf(tmplate,pURL);
  433.       }
  434.   
  435.       if (msg) {
  436.         FE_Alert(pErrorContext,msg);
  437.         XP_FREE(msg);
  438.       }
  439.       else {
  440.         XP_ASSERT(0);
  441.       }
  442.     }
  443.  
  444.     // TRUE says to cancel opening URL.
  445.     if (doneFunction) {
  446.       (*doneFunction)(TRUE, pURL, hook);
  447.     }
  448.     XP_FREE(pURL);
  449.     return;
  450.   }
  451.  
  452.  
  453. #ifdef EDITOR_JAVA
  454.     if ( EditorPluginManager_PluginsExist() ) {
  455.         CEditorPluginInterface* epi = new CEditorPluginInterface(0, &EDT_ComposerPluginCallback);
  456.         char temp[500];
  457.         XP_SPRINTF(temp, "edit:%s", pURL);
  458.         PreOpenCallbackHook* hook2 = new PreOpenCallbackHook;
  459.         hook2->pInterface = epi;
  460.         hook2->doneFunction = doneFunction;
  461.         hook2->pURL = pURL ? XP_STRDUP(pURL) : 0;
  462.         hook2->hook = hook;
  463.         netscape_javascript_JSObject *t_object=LJ_GetMochaWindow(pErrorContext);
  464.         if ( epi->Perform(temp, &edt_PreOpenDoneFunction, hook2, t_object) ){
  465.             XP_FREE(pURL);
  466.             return;
  467.         }
  468.         // Failed, so clean up
  469.         delete epi;
  470.         delete hook2;
  471.     }
  472. #endif
  473.     if ( doneFunction ){
  474.         // FALSE means don't cancel.
  475.         (*doneFunction)(FALSE, pURL, hook);
  476.     }
  477.     XP_FREE(pURL);
  478. }
  479.  
  480. struct PreCloseCallbackHook {
  481.     EDT_PreCloseCallbackFn doneFunction;
  482.     void* hook;
  483. };
  484.  
  485. #ifndef XP_OS2
  486. static 
  487. #else
  488. extern "OPTLINK"
  489. #endif
  490. void edt_PreCloseDoneFunction(EDT_ImageEncoderStatus, void* hook2){
  491.   // Ignore status.
  492.   if (!hook2) {
  493.     XP_ASSERT(0);
  494.     return;
  495.   }
  496.  
  497.   PreCloseCallbackHook *preClose = (PreCloseCallbackHook *)hook2;
  498.   if ( preClose->doneFunction )
  499.       (*preClose->doneFunction)(preClose->hook);
  500.   delete preClose;  
  501. }
  502.  
  503. void EDT_PreClose(MWContext *pMWContext,char* pURL, 
  504.                   EDT_PreCloseCallbackFn doneFunction, void* hook) {
  505.   PreCloseCallbackHook *hook2 = new PreCloseCallbackHook;
  506.   if (!hook2) {
  507.     XP_ASSERT(0);
  508.     return;
  509.   }
  510.   hook2->doneFunction = doneFunction;
  511.   hook2->hook = hook;
  512.  
  513.   // EDT_PerformEvent takes care of #ifdef EDITOR_JAVA.
  514.   EDT_PerformEvent(pMWContext,"close",pURL,FALSE,FALSE,edt_PreCloseDoneFunction,(void *)hook2);
  515. }
  516.  
  517. // End of edt.h API functions
  518.  
  519. #ifdef EDITOR_JAVA
  520.  
  521. #define JAVA_EE_OR_RETURN JRIEnv* ee = Env(); if ( ! ee ) return
  522.  
  523. // Helper class for calling editor plugins
  524.  
  525. extern "C" {
  526.     JRIEnv* npn_getJavaEnv();
  527. }
  528.  
  529. EditorPluginManager EditorPluginManager_new(MWContext* pContext) {
  530.     return new CEditorPluginInterface(pContext, &EDT_ComposerPluginCallback);
  531. }
  532.  
  533. void EditorPluginManager_delete(EditorPluginManager a){
  534.     CEditorPluginInterface* b = (CEditorPluginInterface*) a;
  535.     delete b;
  536. }
  537.  
  538. XP_Bool EditorPluginManager_IsPluginActive(EditorPluginManager a) {
  539.     CEditorPluginInterface* b = (CEditorPluginInterface*) a;
  540.     if ( CEditorPluginInterface::PluginsExist() && b ) {
  541.         return b->IsPluginActive();
  542.     }
  543.     return FALSE;
  544. }
  545.  
  546. XP_Bool EditorPluginManager_PluginsExist() {
  547.     return CEditorPluginInterface::PluginsExist();
  548. }
  549.  
  550. // This method is a modified version of intl_makeJavaString in modules/edtplug/lj_init.c
  551. // Really would like this to be standardized.
  552. PRIVATE PRBool onlyascii2(char* str, int len)
  553. {
  554.     int i;
  555.     for(i = 0 ; i < len ; i++, str++)
  556.     {
  557.         if((*str & 0x80) != 0x00)
  558.             return PR_FALSE;
  559.     }
  560.     return PR_TRUE;
  561. }
  562.  
  563. PRIVATE struct java_lang_String*
  564. intl_makeJavaString2(JRIEnv* env, int16 encoding, char* str, int len)
  565. {
  566.     // First, convert from encoding to win_csid
  567.     encoding &= ~CS_AUTO;
  568.  
  569.     if ((encoding == 0) || 
  570.         ((STATEFUL != (encoding & STATEFUL) ) && onlyascii2(str,len) )
  571.        )
  572.     {
  573.         return JRI_NewStringUTF(env, str, len);
  574.     }
  575.  
  576.     int16 win_csid = INTL_DocToWinCharSetID(encoding) & ~CS_AUTO;
  577.  
  578.     char *str_in_win_csid = NULL;
  579.     int len_in_win_csid = 0;
  580.     XP_Bool needConvertToWincsid = (encoding != win_csid);
  581.     XP_Bool needToFreeMem = needConvertToWincsid;    
  582.     
  583.     if(needConvertToWincsid)
  584.     {
  585.         str_in_win_csid = (char*)INTL_ConvertLineWithoutAutoDetect(
  586.             (int16)encoding, win_csid, (unsigned char*) str, (uint32) len);
  587.         if(NULL == str_in_win_csid )
  588.         {
  589.             str_in_win_csid = str;
  590.             len_in_win_csid = len;
  591.             needToFreeMem = FALSE;
  592.             
  593.         }
  594.         else
  595.         {
  596.             len_in_win_csid = (int)XP_STRLEN( str_in_win_csid );
  597.         }
  598.     }    
  599.     else
  600.     {
  601.         str_in_win_csid = str;
  602.         len_in_win_csid = len;
  603.     }
  604.     // Second, convert from win_csid to Unicode
  605.     INTL_Unicode* q;
  606.     int unicodelen, realunicodelen;
  607.     unicodelen = INTL_TextToUnicodeLen(win_csid, 
  608.         (unsigned char*)str_in_win_csid, (int32)len_in_win_csid);
  609.     
  610.     struct java_lang_String* result;
  611.     if ((q = (INTL_Unicode*) XP_ALLOC(sizeof(INTL_Unicode) * unicodelen)) != NULL) {
  612.         realunicodelen = INTL_TextToUnicode(win_csid, 
  613.             (unsigned char*)str_in_win_csid, len_in_win_csid, q, unicodelen );
  614.     
  615.         result = JRI_NewString(env, (const jchar*)q, realunicodelen);
  616.         XP_FREE(q);
  617.     } else {
  618.         XP_ASSERT(q);
  619.         result = JRI_NewStringUTF(env, str, len);
  620.     }
  621.  
  622.     // Finally, let's free some memory
  623.     if(needToFreeMem && str_in_win_csid)
  624.     {
  625.         XP_FREE(str_in_win_csid);
  626.     }
  627.  
  628.     return result;
  629. }
  630.  
  631. // Returns length accurately.
  632. // returns NULL if the string is too large for the platform.
  633. PRIVATE char*
  634. intl_makeStringFromJava(JRIEnv* env, int16 encoding, struct java_lang_String* jstr, int32& length)
  635. {
  636.     const jchar * juc = JRI_GetStringChars(env, jstr);
  637.     uint32 jucLen = JRI_GetStringLength(env, jstr);
  638.     if ( jucLen > (uint32) MAX_STRING ) {
  639.         length = jucLen;
  640.         return 0;
  641.     }
  642.  
  643.     encoding &= ~CS_AUTO;
  644.     int16 win_csid = INTL_DocToWinCharSetID(encoding) & ~CS_AUTO;
  645.  
  646.     length = INTL_UnicodeToStrLen(win_csid, (INTL_Unicode*) juc, jucLen);
  647.     if ( length > MAX_STRING ) {
  648.         return 0;
  649.     }
  650.     char* text_in_win_csid = (char*) XP_ALLOC(length + 1);
  651.     if ( ! text_in_win_csid ) {
  652.         return 0;
  653.     }
  654.     INTL_UnicodeToStr(win_csid, (INTL_Unicode*) juc, jucLen, (unsigned char*) text_in_win_csid, length + 1);
  655.  
  656.     char* text_in_encoding = NULL;
  657.     if(encoding == win_csid)
  658.     {
  659.         text_in_encoding = text_in_win_csid;
  660.     }
  661.     else
  662.     {
  663.         text_in_encoding = (char*)INTL_ConvertLineWithoutAutoDetect(
  664.             win_csid, (int16)encoding, (unsigned char*) text_in_win_csid, 
  665.             (uint32) XP_STRLEN(text_in_win_csid));
  666.         if ( ! text_in_encoding ){
  667.             text_in_encoding = text_in_win_csid;
  668.         }
  669.         else {
  670.             XP_FREE(text_in_win_csid);
  671.         }
  672.     }
  673.     return text_in_encoding;
  674.  
  675. }
  676.  
  677. XP_Bool CEditorPluginInterface::PluginsExist(){
  678.     return g_Plugin.Size() > 0;
  679. }
  680.  
  681. JRIGlobalRef CEditorPluginInterface::g_pManager;
  682. JRIEnv* CEditorPluginInterface::g_pEnv;
  683. XP_Bool CEditorPluginInterface::g_bJavaInitialized;
  684.  
  685. JRIEnv* CEditorPluginInterface::Env(){
  686.     if ( ! g_bJavaInitialized ) {
  687.         g_bJavaInitialized = TRUE;
  688.         g_pEnv = npn_getJavaEnv();
  689.         if ( g_pEnv == NULL ) {
  690.             XP_TRACE(("CEditorPluginInterface::Env() - Could not start Java."));
  691.             return NULL;
  692.         }
  693.         JRIEnv* ee = g_pEnv;
  694.         JRI_ExceptionClear(ee);
  695.         use_netscape_plugin_composer_PluginManager(ee);
  696.         use_netscape_plugin_composer_Composer(ee);
  697.         use_netscape_plugin_composer_MozillaCallback(ee);
  698.         if ( JRI_ExceptionOccurred(ee)){
  699.             JRI_ExceptionDescribe(ee);
  700.             XP_TRACE(("Couldn't find PluginManager class."));
  701.             return g_pEnv;
  702.         }
  703.         g_pManager = JRI_NewGlobalRef(ee, netscape_plugin_composer_PluginManager_new(ee,
  704.             class_netscape_plugin_composer_PluginManager(ee)));
  705.  
  706.         if ( ! Manager() || JRI_ExceptionOccurred(ee)){
  707.             JRI_ExceptionDescribe(ee);
  708.             XP_TRACE(("Couldn't create PluginManager instance."));
  709.         }
  710.  
  711.         // Tell the plugin manager about the plugins
  712.         int size = g_Plugin.Size();
  713.         for(int i = 0; i < size; i++ ){
  714.             char* pPlugin = g_Plugin[i];
  715.             // Until we get java based local file i/o working, help out the plugin by
  716.             // reading the ini text here.
  717.             static const char* kComposerIni = "netscape_plugin_composer.ini";
  718.  
  719.             zip_t* pZip = zip_open(pPlugin);
  720.             if ( pZip ) {
  721.                 struct stat status;
  722.                 if ( zip_stat(pZip, kComposerIni, &status)){
  723.                     int32_t len = status.st_size;
  724.                     if ( len > 0 ) {
  725.                         char* pBuffer = new char[len];
  726.                         if ( zip_get(pZip, kComposerIni, pBuffer, len) ){
  727.                             struct java_lang_String* pluginINI = (struct java_lang_String*)
  728.                                 JRI_NewStringUTF(ee, pBuffer, len);
  729.                             struct java_lang_String* pluginFileName = (struct java_lang_String*)
  730.                                 JRI_NewStringUTF(ee, pPlugin, XP_STRLEN(pPlugin));
  731.                             JRI_ExceptionClear(ee);
  732.                             netscape_plugin_composer_PluginManager_registerPlugin(ee, Manager(),
  733.                                 pluginFileName, pluginINI);
  734.                             if ( JRI_ExceptionOccurred(ee)){
  735.                                 JRI_ExceptionDescribe(ee);
  736.                                 XP_TRACE(("Couldn't registerPlugin %s", pPlugin));
  737.                             }
  738.                         }
  739.                     }
  740.                 }
  741.                 zip_close(pZip);
  742.             }
  743.         }
  744.     }
  745.     return g_pEnv;
  746. }
  747.  
  748. netscape_plugin_composer_PluginManager* CEditorPluginInterface::Manager(){
  749.     JAVA_EE_OR_RETURN 0;
  750.     return (netscape_plugin_composer_PluginManager*) JRI_GetGlobalRef(ee, g_pManager);
  751. }
  752.  
  753. netscape_plugin_composer_Composer* CEditorPluginInterface::Composer(){
  754.     JAVA_EE_OR_RETURN 0;
  755.     return (netscape_plugin_composer_Composer*) JRI_GetGlobalRef(ee, m_pComposer);
  756. }
  757.  
  758.  
  759. TXP_GrowableArray_pChar CEditorPluginInterface::g_Plugin;
  760. TXP_GrowableArray_CEditorPluginInterface CEditorPluginInterface::g_Interface;
  761.  
  762. CEditorPluginInterface::CEditorPluginInterface(MWContext* pContext, ComposerPluginCallbackFn callback){
  763.     m_pContext = pContext;
  764.     m_callback = callback;
  765.     m_bPluginActive = FALSE;
  766.     m_doneFunction = 0;
  767.     m_pComposer = 0;
  768.     m_bImageEncoder = FALSE;
  769.     JAVA_EE_OR_RETURN;
  770.     m_pComposer = JRI_NewGlobalRef(ee, netscape_plugin_composer_Composer_new(ee,
  771.         class_netscape_plugin_composer_Composer(ee),
  772.         (jint) this, (jint) m_callback, (jint) ee));
  773.     g_Interface.Add(this);
  774. }
  775.  
  776. CEditorPluginInterface::~CEditorPluginInterface(){
  777.     int size = g_Interface.Size();
  778.     int i = 0;
  779.     for(i = 0; i < size; i++ ){
  780.         if ( g_Interface[i] == this ) {
  781.             break;
  782.         }
  783.     }
  784.     if ( i < size ) {
  785.         for(i++; i < size; i++){
  786.             g_Interface[i-1] = g_Interface[i];
  787.         }
  788.         g_Interface.SetSize(size-1);
  789.     }
  790.     else {
  791.         XP_ASSERT(FALSE); // We didn't find ourselves in the interface registry.
  792.     }
  793.     JAVA_EE_OR_RETURN;
  794.     JRI_DisposeGlobalRef(ee, m_pComposer);
  795. #if 0
  796.     netscape_plugin_composer_PluginManager::_unuse(ee);
  797. #endif
  798. }
  799.  
  800. XP_Bool CEditorPluginInterface::IsValidInterface(CEditorPluginInterface* pInterface){
  801.     int i = 0;
  802.     int size = g_Interface.Size();
  803.     for(i = 0; i < size; i++ ){
  804.         if ( g_Interface[i] == pInterface ) {
  805.             return TRUE;
  806.         }
  807.     }
  808.     return FALSE;
  809. }
  810.  
  811. void CEditorPluginInterface::Register(char* plugin){
  812.     // This method is called before Java is initialized.
  813.     // It is designed so that it doesn't need Java to run.
  814.     // The names of the plugin files are saved until later.
  815.     //
  816.     // This way, we don't start Java until the Composer is started.
  817.  
  818.     int size = g_Plugin.Size();
  819.     for(int i = 0; i < size; i++ ){
  820.         if ( XP_STRCMP(g_Plugin[i], plugin) == 0 ) {
  821.             return;
  822.         }
  823.     }
  824.  
  825.     // If We've started Java, it's too late to add the plug-in.
  826.     if ( g_bJavaInitialized ) {
  827.         // to do: Allow Composer plug-ins to be added after starting.
  828.         return;
  829.     }
  830.     // We don't have to add this plugin to the class path because
  831.     // LJ_AddToClassPath puts every .zip or .jar file in
  832.     // the plug-ins directory into the class path.
  833.  
  834.     // Save the plugin name.
  835.     int len = XP_STRLEN(plugin);
  836.     char* pCopy = (char*) XP_ALLOC(len+1);
  837.     if ( pCopy ) {
  838.         XP_STRCPY(pCopy, plugin);
  839.         g_Plugin.Add(pCopy);
  840.     }
  841. }
  842.  
  843. int32 CEditorPluginInterface::GetNumberOfCategories(){
  844.     if ( ! PluginsExist() ) return 0;
  845.     JAVA_EE_OR_RETURN 0;
  846.     if ( ! Manager() ) {
  847.         return 0;
  848.     }
  849.     JRI_ExceptionClear(ee);
  850.     int numPlugins = netscape_plugin_composer_PluginManager_getNumberOfCategories(ee, Manager());
  851.     if ( JRI_ExceptionOccurred(ee)){
  852.         JRI_ExceptionDescribe(ee);
  853.         XP_TRACE(("Couldn't getNumberOfCategories."));
  854.         return 0;
  855.     }
  856.     return numPlugins;
  857. }
  858.  
  859. int32 CEditorPluginInterface::GetNumberOfPlugins(int32 type){
  860.     if ( ! PluginsExist() ) return 0;
  861.     JAVA_EE_OR_RETURN 0;
  862.     if ( ! Manager() ) {
  863.         return 0;
  864.     }
  865.     JRI_ExceptionClear(ee);
  866.     int numPlugins = netscape_plugin_composer_PluginManager_getNumberOfPlugins(ee, Manager(), type);
  867.     if ( JRI_ExceptionOccurred(ee)){
  868.         JRI_ExceptionDescribe(ee);
  869.         XP_TRACE(("Couldn't getNumberOfPlugins."));
  870.         return 0;
  871.     }
  872.     return numPlugins;
  873. }
  874.  
  875. static char*
  876. getPlatformString(JRIEnv* ee, java_lang_String* name)
  877. {
  878.     if (name == NULL || JRI_ExceptionOccurred(ee)){
  879. #ifdef DEBUG
  880.         JRI_ExceptionDescribe(ee);
  881. #endif
  882.         XP_TRACE(("Couldn't get composer plugin field."));
  883.         return NULL;
  884.     }
  885.     /* Get the platform encoding of the string based on the browser's default csid */
  886.     char* result = (char*) JRI_GetStringPlatformChars(ee, name, NULL, 0);
  887.     if (result == NULL) {
  888.         XP_TRACE(("Couldn't convert unicode string to platform string."));
  889.         return NULL;
  890.     }
  891.     else if (JRI_ExceptionOccurred(ee)) {
  892. #ifdef DEBUG
  893.         JRI_ExceptionDescribe(ee);
  894. #endif
  895.         XP_TRACE(("Couldn't convert unicode string to platform string."));
  896.         return NULL;
  897.     }
  898.     return result;
  899. }
  900.  
  901. char* CEditorPluginInterface::GetCategoryName(int32 type){
  902.     char* result = 0;
  903.     if ( ! PluginsExist() ) return result;
  904.     JAVA_EE_OR_RETURN result;
  905.     if ( ! Manager() ) {
  906.         return result;
  907.     }
  908.     JRI_ExceptionClear(ee);
  909.     java_lang_String* name = netscape_plugin_composer_PluginManager_getCategoryName(ee, Manager(), type);
  910.     return getPlatformString(ee, name);
  911. }
  912.  
  913. char* CEditorPluginInterface::GetPluginName(int32 type, int32 index){
  914.     char* result = 0;
  915.     if ( ! PluginsExist() ) return result;
  916.     JAVA_EE_OR_RETURN result;
  917.     if ( ! Manager() ) {
  918.         return result;
  919.     }
  920.     JRI_ExceptionClear(ee);
  921.     java_lang_String* name = netscape_plugin_composer_PluginManager_getPluginName(ee, Manager(), type, index);
  922.     return getPlatformString(ee, name);
  923. }
  924.  
  925. char* CEditorPluginInterface::GetPluginHint(int32 type, int32 index){
  926.     char* result = 0;
  927.     if ( ! PluginsExist() ) return result;
  928.     JAVA_EE_OR_RETURN result;
  929.     if ( ! Manager() ) {
  930.         return result;
  931.     }
  932.     JRI_ExceptionClear(ee);
  933.     java_lang_String* hint = netscape_plugin_composer_PluginManager_getPluginHint(ee, Manager(), type, index);
  934.     return getPlatformString(ee, hint);
  935. }
  936.  
  937. int32 CEditorPluginInterface::GetNumberOfEncoders(){
  938.     if ( ! PluginsExist() ) return 0;
  939.     JAVA_EE_OR_RETURN 0;
  940.     if ( ! Manager() ) {
  941.         return 0;
  942.     }
  943.     JRI_ExceptionClear(ee);
  944.     int32 result = netscape_plugin_composer_PluginManager_getNumberOfEncoders(ee, Manager());
  945.     if ( JRI_ExceptionOccurred(ee)){
  946.         JRI_ExceptionDescribe(ee);
  947.         XP_TRACE(("Couldn't getNumberOfEncoders."));
  948.         return 0;
  949.     }
  950.     return result;
  951. }
  952.  
  953. char* CEditorPluginInterface::GetEncoderName(int32 index){
  954.     char* result = 0;
  955.     if ( ! PluginsExist() ) return result;
  956.     JAVA_EE_OR_RETURN result;
  957.     if ( ! Manager() ) {
  958.         return result;
  959.     }
  960.     JRI_ExceptionClear(ee);
  961.     java_lang_String* hint = netscape_plugin_composer_PluginManager_getEncoderName(ee, Manager(), index);
  962.     return getPlatformString(ee, hint);
  963. }
  964.  
  965. char* CEditorPluginInterface::GetEncoderHint(int32 index){
  966.     char* result = 0;
  967.     if ( ! PluginsExist() ) return result;
  968.     JAVA_EE_OR_RETURN result;
  969.     if ( ! Manager() ) {
  970.         return result;
  971.     }
  972.     JRI_ExceptionClear(ee);
  973.     java_lang_String* hint = netscape_plugin_composer_PluginManager_getEncoderHint(ee, Manager(), index);
  974.     return getPlatformString(ee, hint);
  975. }
  976.  
  977. char* CEditorPluginInterface::GetEncoderFileExtension(int32 index){
  978.     char* result = 0;
  979.     if ( ! PluginsExist() ) return result;
  980.     JAVA_EE_OR_RETURN result;
  981.     if ( ! Manager() ) {
  982.         return result;
  983.     }
  984.     JRI_ExceptionClear(ee);
  985.     java_lang_String* hint = netscape_plugin_composer_PluginManager_getEncoderFileExtension(ee, Manager(), index);
  986.     return getPlatformString(ee, hint);
  987. }
  988.  
  989. char* CEditorPluginInterface::GetEncoderFileType(int32 index){
  990.     char* result = 0;
  991.     if ( ! PluginsExist() ) return result;
  992.     JAVA_EE_OR_RETURN result;
  993.     if ( ! Manager() ) {
  994.         return result;
  995.     }
  996.     JRI_ExceptionClear(ee);
  997.     java_lang_String* hint = netscape_plugin_composer_PluginManager_getEncoderFileType(ee, Manager(), index);
  998.     return getPlatformString(ee, hint);
  999. }
  1000.  
  1001. XP_Bool CEditorPluginInterface::GetEncoderNeedsQuantizedSource(int32 index){
  1002.     XP_Bool result = FALSE;
  1003.     if ( ! PluginsExist() ) return result;
  1004.     JAVA_EE_OR_RETURN result;
  1005.     if ( ! Manager() ) {
  1006.         return result;
  1007.     }
  1008.     JRI_ExceptionClear(ee);
  1009.     result = netscape_plugin_composer_PluginManager_getEncoderNeedsQuantizedSource(ee, Manager(), index);
  1010.     if ( JRI_ExceptionOccurred(ee)){
  1011.         JRI_ExceptionDescribe(ee);
  1012.         XP_TRACE(("Couldn't getEncoderNeedsQuantizedSource."));
  1013.         return result;
  1014.     }
  1015.     return result;
  1016. }
  1017.  
  1018. XP_Bool CEditorPluginInterface::StartEncoder(int32 index, int32 width, int32 height, char** pixels,
  1019.     char* csFileName, EDT_ImageEncoderCallbackFn doneFunction,
  1020.     void* doneArgument){
  1021.     if ( ! PluginsExist() ) return FALSE;
  1022.     JAVA_EE_OR_RETURN FALSE;
  1023.     if ( ! Manager() ) {
  1024.         return FALSE;
  1025.     }
  1026.     m_bCanChangeDocument = FALSE;
  1027.     m_bCanCancel = TRUE;
  1028.     m_bImageEncoder = TRUE;
  1029.     // Convert the file name
  1030.     struct java_lang_String* javaFileName = (struct java_lang_String*)
  1031.         JRI_NewStringUTF(ee, csFileName, XP_STRLEN(csFileName));
  1032.  
  1033.     jarrayArray javaPixels = (jarrayArray) JRI_NewObjectArray(ee, height,
  1034.         JRI_FindClass(ee, JRISigArray(JRISigByte)) , NULL);
  1035.     {
  1036.         // Convert the pixels to Java data struct
  1037.         int32 byteLength = width * 3;
  1038.         // Fill it up with the lines
  1039.         for(int hh = 0; hh < height; hh++){
  1040.             jbyteArray a = (jbyteArray) JRI_NewByteArray(ee, byteLength, pixels[hh]);
  1041.             JRI_SetObjectArrayElement(ee, javaPixels, hh, a);
  1042.         }
  1043.     }
  1044.     // Save the callback info.
  1045.     m_doneFunction = doneFunction;
  1046.     m_doneFunctionArgument = doneArgument;
  1047.     m_bPluginActive = TRUE;
  1048.     // call the encoder
  1049.     JRI_ExceptionClear(ee);
  1050.     XP_Bool result = (XP_Bool)
  1051.         netscape_plugin_composer_PluginManager_startEncoder(ee, Manager(), Composer(), index, width, height, javaPixels, javaFileName);
  1052.     if ( JRI_ExceptionOccurred(ee)){
  1053.         JRI_ExceptionDescribe(ee);
  1054.         XP_TRACE(("Couldn't start encoder."));
  1055.         m_bPluginActive = FALSE;
  1056.         result = FALSE;
  1057.     }
  1058.     return result;
  1059. }
  1060.  
  1061. XP_Bool CEditorPluginInterface::Perform(int32 type, int32 index, EDT_ImageEncoderCallbackFn doneFunction, void* hook, netscape_javascript_JSObject *jsobject){
  1062.     return Perform2(NULL, type, index, TRUE, TRUE, doneFunction, hook, jsobject);
  1063. }
  1064.  
  1065. XP_Bool CEditorPluginInterface::Perform(char* pPluginName, EDT_ImageEncoderCallbackFn doneFunction, void* hook, netscape_javascript_JSObject *jsobject){
  1066.     return Perform2(pPluginName, 0, 0, TRUE, TRUE, doneFunction, hook, jsobject);
  1067. }
  1068.  
  1069. void CEditorPluginInterface::Perform(char* pEvent, char* pDocURL, XP_Bool bCanChangeDocument, XP_Bool bCanCancel,
  1070.                                      EDT_ImageEncoderCallbackFn doneFunction, void* hook, netscape_javascript_JSObject *jsobject){
  1071.     char *pEventName = NULL;
  1072.     StrAllocCat(pEventName,pEvent);
  1073.     StrAllocCat(pEventName,":");
  1074.     if ( pDocURL ) {
  1075.         StrAllocCat(pEventName,pDocURL);
  1076.     }
  1077.     XP_Bool result = Perform2(pEventName, 0, 0, bCanChangeDocument, bCanCancel, doneFunction, hook, jsobject);
  1078.     XP_FREE(pEventName);
  1079.     if ( !result && doneFunction ) {
  1080.         (*doneFunction)(ED_IMAGE_ENCODER_EXCEPTION, hook);
  1081.     }
  1082. }
  1083.  
  1084. XP_Bool CEditorPluginInterface::Perform2(char* pPluginName, int32 type, int32 index,
  1085.         XP_Bool bCanChangeDocument, XP_Bool bCanCancel,
  1086.         EDT_ImageEncoderCallbackFn doneFunction, void* hook, netscape_javascript_JSObject *jsobject){
  1087.     m_bCanChangeDocument = bCanChangeDocument;
  1088.     m_bCanCancel = bCanCancel;
  1089.     m_bImageEncoder = FALSE;
  1090.     if ( ! pPluginName && ! PluginsExist() ) {
  1091.         return FALSE;
  1092.     }
  1093.     if ( m_bPluginActive ) {
  1094.         return FALSE;
  1095.     }
  1096.     JAVA_EE_OR_RETURN FALSE;
  1097.     if ( ! Manager() ) {
  1098.         return FALSE;
  1099.     }
  1100.  
  1101.     struct java_lang_String* document = GetDocument();
  1102.     // It is OK for the document to be NULL if we have
  1103.     // no buffer. (This can happen during an edit event.)
  1104.     // Otherwise, it is an error condition. NULL is returned
  1105.     // when the document is too large for Win16.
  1106.     if ( document==NULL && GetBuffer() != NULL){
  1107.         return FALSE;
  1108.     }
  1109.     struct java_lang_String* base = GetBaseURL();
  1110.     struct java_lang_String* workDirectoryURL = 0;
  1111.     struct java_lang_String* workDirectory = 0;
  1112.     GetWorkDirectoryAndURL(workDirectory, workDirectoryURL);
  1113.     m_bChangedDocument = FALSE;
  1114.     // call the plugin
  1115.     JRI_ExceptionClear(ee);
  1116.     
  1117.     XP_Bool bResult = FALSE;
  1118.     m_doneFunction = doneFunction;
  1119.     m_doneFunctionArgument = hook;
  1120.  
  1121.     if ( pPluginName ) {
  1122.         // Call plugin by class name.
  1123.         struct java_lang_String* pluginName = (struct java_lang_String*)
  1124.             JRI_NewStringUTF(ee, pPluginName, XP_STRLEN(pPluginName));
  1125.         JRI_ExceptionClear(ee);
  1126.         bResult = netscape_plugin_composer_PluginManager_performPluginByName(ee, Manager(), Composer(),
  1127.             pluginName, document, base, workDirectory, workDirectoryURL, jsobject);
  1128.     }
  1129.     else {
  1130.         // Call plugin by menu category and index
  1131.         JRI_ExceptionClear(ee);
  1132.         bResult = netscape_plugin_composer_PluginManager_performPlugin(ee, Manager(), Composer(),
  1133.             type, index, document, base, workDirectory, workDirectoryURL, jsobject);
  1134.     }
  1135.     if ( JRI_ExceptionOccurred(ee)){
  1136.         JRI_ExceptionDescribe(ee);
  1137.         bResult = FALSE;
  1138.     }
  1139.  
  1140.     if ( bResult == FALSE ) {
  1141.         XP_TRACE(("Couldn't perform."));
  1142.         m_doneFunction = 0;
  1143.         m_doneFunctionArgument = 0;
  1144.         return FALSE;
  1145.     }
  1146.  
  1147.     m_bPluginActive = TRUE;
  1148.     if ( GetBuffer() ){
  1149.         GetBuffer()->m_pContext->waitingMode = 1;
  1150.     }
  1151.     return TRUE;
  1152. }
  1153.  
  1154. struct java_lang_String* CEditorPluginInterface::GetBaseURL(){
  1155.     if ( GetBuffer() == 0 ) {
  1156.         return 0;
  1157.     }
  1158.     JAVA_EE_OR_RETURN 0;
  1159.     char* pBase = LO_GetBaseURL(GetBuffer()->m_pContext); // an alias. We don't own the result.
  1160.     int32 iBaseLen = XP_STRLEN(pBase);
  1161.     struct java_lang_String* base = (struct java_lang_String*)
  1162.         JRI_NewStringUTF(ee, pBase, iBaseLen);
  1163.     return base;
  1164. }
  1165.  
  1166. struct java_lang_String* CEditorPluginInterface::GetDocument(){
  1167.     if ( GetBuffer() == 0 ) {
  1168.         return 0;
  1169.     }
  1170.     JAVA_EE_OR_RETURN 0;
  1171.     XP_HUGE_CHAR_PTR pDocData = 0;
  1172.     int32 docLength = 0;
  1173.  
  1174.     docLength = GetBuffer()->WriteToBuffer(&pDocData, TRUE);
  1175.     if ( docLength > MAX_STRING ) {
  1176.         DocumentIsTooLarge(docLength, XP_EDT_CP_DOCUMENT_TOO_LARGE_READ);
  1177.         return 0;
  1178.     }
  1179.  
  1180.     int32 unicodeByteLength = 2 * (int32) INTL_TextToUnicodeLen(GetBuffer()->GetDocCharSetID(), (unsigned char*)pDocData, docLength);
  1181.     if ( unicodeByteLength > MAX_STRING ) {
  1182.         DocumentIsTooLarge(unicodeByteLength, XP_EDT_CP_DOCUMENT_TOO_LARGE_READ);
  1183.         return 0;
  1184.     }
  1185.  
  1186.     struct java_lang_String* document = (struct java_lang_String*)
  1187.         intl_makeJavaString2(ee, GetBuffer()->GetDocCharSetID(), pDocData, docLength);
  1188.  
  1189.     if ( pDocData ) {
  1190.         XP_HUGE_FREE(pDocData);
  1191.     }
  1192.     return document;
  1193. }
  1194.  
  1195. void CEditorPluginInterface::DocumentIsTooLarge(int32 docLengthInBytes, int msgid){
  1196.     // Tell the user that the document is too big.
  1197.     char* tmplate = XP_GetString(msgid);
  1198.     if (tmplate) {
  1199.         char* msg = PR_smprintf(tmplate,docLengthInBytes, MAX_STRING);
  1200.         if (msg) {
  1201.             FE_Alert(m_pContext,msg);
  1202.             XP_FREE(msg);
  1203.         }
  1204.     }
  1205. }
  1206.  
  1207. void CEditorPluginInterface::GetWorkDirectoryAndURL(
  1208.         struct java_lang_String*& workDirectory,
  1209.         struct java_lang_String*& workDirectoryURL){
  1210.     workDirectory = 0;
  1211.     workDirectoryURL = 0;
  1212.     if ( GetBuffer() == 0 ) {
  1213.         return;
  1214.     }
  1215.     JAVA_EE_OR_RETURN;
  1216.     // Get the work directory
  1217.     char* pWork = NULL; // We own the storage
  1218.  
  1219.     char* pBase = LO_GetBaseURL(GetBuffer()->m_pContext); // an alias. We don't own the result.
  1220.     int baseURLType = NET_URL_Type(pBase);
  1221.     if (baseURLType == FILE_TYPE_URL) {
  1222.         // Get the file name out of the base URL
  1223.         XP_Bool bValidBase = XP_ConvertUrlToLocalFile(pBase, &pWork);
  1224.         XP_FREE(pWork);
  1225.         pWork = NULL;
  1226.         if ( bValidBase) {
  1227.             // OK, the base file exists. Now we need pWork to hold the directory rather than the
  1228.             // file.
  1229.             char* pTemp = XP_STRDUP(pBase);
  1230.             if ( pTemp != NULL ) {
  1231.                 char* pEnd = pTemp + XP_STRLEN(pTemp) - 1;
  1232.                 while ( pEnd > pTemp && *pEnd != '/') {
  1233.                     pEnd--;
  1234.                 }
  1235.                 if (* pEnd == '/') {
  1236.                     *pEnd = '\0';
  1237.                     XP_ConvertUrlToLocalFile(pTemp, &pWork);
  1238.                 }
  1239.                 XP_FREE(pTemp);
  1240.             }
  1241.         }
  1242.     }
  1243.  
  1244.     if ( pWork == NULL ) { 
  1245.       // If we can't use document current directory, use document temp directory.
  1246.       CEditCommandLog *pLog = CGlobalHistoryGroup::GetGlobalHistoryGroup()->GetLog(GetBuffer());
  1247.       if (pLog) {
  1248.         char *pxpURL = pLog->GetDocTempDir();
  1249.         if (pxpURL) {
  1250.           pWork = WH_FileName(pxpURL,xpURL);
  1251.           XP_FREE(pxpURL);
  1252.         }
  1253.       }
  1254.     }
  1255.  
  1256.     if ( pWork != NULL ) {
  1257.         int32 iWorkLen = XP_STRLEN(pWork);
  1258.  
  1259.         workDirectory = (struct java_lang_String*)
  1260.             JRI_NewStringUTF(ee, pWork, iWorkLen);
  1261.         // And what's the URL that corresponds to the work directory?
  1262.         char* pWorkURL = XP_PlatformFileToURL(pWork);
  1263.  
  1264.         int32 iWorkURLLen = XP_STRLEN(pWorkURL);
  1265.  
  1266.         workDirectoryURL = (struct java_lang_String*)
  1267.             JRI_NewStringUTF(ee, pWorkURL, iWorkURLLen);
  1268.  
  1269. #ifdef DEBUG_rhess
  1270.         fprintf(stderr, "     workDir::[ %s ]\n", pWork);
  1271.         fprintf(stderr, "  workDirURL::[ %s ]\n", pWorkURL);
  1272. #endif
  1273.         XP_FREE(pWork);
  1274.         XP_FREE(pWorkURL);
  1275.     }
  1276. #ifdef DEBUG_rhess
  1277.     else {
  1278.         fprintf(stderr, "     workDir::[ NULL ]\n");
  1279.         fprintf(stderr, "  workDirURL::[ NULL ]\n");
  1280.     }
  1281. #endif
  1282. }
  1283.  
  1284. XP_Bool CEditorPluginInterface::IsPluginActive(){
  1285.     return m_bPluginActive;
  1286. }
  1287.  
  1288. void CEditorPluginInterface::StopPlugin(){
  1289.     if ( ! PluginsExist() ) return;
  1290.     JAVA_EE_OR_RETURN;
  1291.     JRI_ExceptionClear(ee);
  1292.     netscape_plugin_composer_PluginManager_stopPlugin(ee, Manager(), Composer());
  1293.     if ( JRI_ExceptionOccurred(ee)){
  1294.         JRI_ExceptionDescribe(ee);
  1295.         XP_TRACE(("Couldn't stop plugin."));
  1296.     }
  1297.     m_bPluginActive = FALSE;
  1298.     if ( GetBuffer()){
  1299.         if ( m_bChangedDocument) {
  1300.             GetBuffer()->EndBatchChanges();
  1301.         }
  1302.         GetBuffer()->m_pContext->waitingMode = 0;
  1303.     }
  1304. }
  1305.  
  1306. void CEditorPluginInterface::PluginCallback(int32 action,
  1307.     struct java_lang_Object* pArgument)
  1308. {
  1309.     if ( ! PluginsExist() ) return;
  1310.     switch ( action ) {
  1311.     case PLUGIN_FAIL:
  1312.     case PLUGIN_CANCEL:
  1313.         // The plugin has failed.
  1314.         if ( m_bCanCancel ) {
  1315.             PluginFailed((struct java_lang_String*) pArgument);
  1316.         }
  1317.         else {
  1318.             PluginSucceeded();
  1319.         }
  1320.  
  1321.         break;
  1322.     case PLUGIN_OK:
  1323.         // The plugin has succeeded.
  1324.         PluginSucceeded();
  1325.         break;
  1326.     case PLUGIN_NEWTEXT:
  1327.         // The plugin has changed the text.
  1328.         NewText((struct java_lang_String*) pArgument);
  1329.         break;
  1330.     default:
  1331.         // Unknown callack
  1332.         XP_TRACE(("Unknown Composer Plugin Callback: %d\n", action));
  1333.         break;
  1334.     }
  1335. }
  1336.  
  1337. void CEditorPluginInterface::PluginFailed(struct java_lang_String* pWhy){
  1338.     XP_TRACE(("CEditorPluginInterface::PluginFailed."));
  1339.     m_bPluginActive = FALSE;
  1340.     ImageEncoderFinished(pWhy ? ED_IMAGE_ENCODER_EXCEPTION : ED_IMAGE_ENCODER_USER_CANCELED);
  1341.     if ( m_bImageEncoder ) return;
  1342.     // The user canceled, or the plugin threw an exception. Back out
  1343.     // any change the user may have made to the document.
  1344.     if ( GetBuffer() ){
  1345.         if (m_bChangedDocument) {
  1346.             GetBuffer()->EndBatchChanges();
  1347.         }
  1348.         GetBuffer()->m_pContext->waitingMode = 0;
  1349.         if (m_bChangedDocument) {
  1350.             GetBuffer()->Undo(); // After this call, GetBuffer() is deleted.
  1351.         }
  1352.     }
  1353. }
  1354.  
  1355. void CEditorPluginInterface::PluginSucceeded(){
  1356.     XP_TRACE(("CEditorPluginInterface::PluginSucceeded."));
  1357.     m_bPluginActive = FALSE;
  1358.     ImageEncoderFinished(ED_IMAGE_ENCODER_OK);
  1359.     if ( m_bImageEncoder ) return;
  1360.     if ( GetBuffer() ){
  1361.         if (m_bChangedDocument) {
  1362.             GetBuffer()->EndBatchChanges();
  1363.         }
  1364.         GetBuffer()->m_pContext->waitingMode = 0;
  1365.     }
  1366. }
  1367.  
  1368. void CEditorPluginInterface::ImageEncoderFinished(EDT_ImageEncoderStatus status){
  1369.     if ( ! m_doneFunction ) {
  1370.         return;
  1371.     }
  1372.     (*m_doneFunction)(status, m_doneFunctionArgument);
  1373.     m_doneFunction = 0;
  1374.     m_doneFunctionArgument = 0;
  1375. }
  1376.  
  1377. void CEditorPluginInterface::NewText(struct java_lang_String* pText){
  1378.     XP_TRACE(("CEditorPluginInterface::NewText."));
  1379.     JAVA_EE_OR_RETURN;
  1380.     
  1381.     if ( pText && m_bCanChangeDocument ) {
  1382.  
  1383.         int32 length;
  1384.         int16 csid = 0;
  1385.         if ( GetBuffer() ) {
  1386.             csid = GetBuffer()->GetDocCharSetID();
  1387.         }
  1388.         char* pElementsAsChar =
  1389.             intl_makeStringFromJava(ee, csid, pText, length);
  1390.         if ( !pElementsAsChar ){
  1391.             DocumentIsTooLarge(length, XP_EDT_CP_DOCUMENT_TOO_LARGE_WRITE);
  1392.             return;
  1393.         }
  1394.  
  1395.         if ( m_bChangedDocument == FALSE ) {
  1396.             m_bChangedDocument = TRUE;
  1397.             if ( GetBuffer() ) {
  1398.                 GetBuffer()->BeginBatchChanges(kPerformPluginCommandID);
  1399.             }
  1400.         }
  1401.  
  1402.         if ( pElementsAsChar ) {
  1403.             if ( GetBuffer() ) {
  1404.                 length++; // for '\0' at end.
  1405.                 XP_HUGE_CHAR_PTR pElements = (XP_HUGE_CHAR_PTR) XP_HUGE_ALLOC(length);
  1406.                 for(int32 i = 0; i < length; i++ ) {
  1407.                     pElements[i] = pElementsAsChar[i];
  1408.                 }
  1409.                 GetBuffer()->ReadFromBuffer(pElements);
  1410.                 // At this point GetBuffer() is deleted.
  1411.                 XP_HUGE_FREE(pElements);
  1412.             }
  1413.             else { // Call-back hack for setting the URL during preOpen
  1414.                 edt_SetURL(m_doneFunctionArgument, pElementsAsChar);
  1415.             }
  1416.             XP_FREE(pElementsAsChar);
  1417.         }
  1418.     }
  1419. }
  1420.  
  1421. CEditBuffer* CEditorPluginInterface::GetBuffer(){
  1422.     if ( ! m_pContext ) return 0;
  1423.     GET_EDIT_BUF_OR_RETURN_READY_OR_NOT(m_pContext, pEditBuffer) NULL;
  1424.     return pEditBuffer;
  1425. }
  1426.  
  1427. #endif // EDITOR_JAVA
  1428. #endif // EDITOR
  1429.