/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ /* * Event handling in the Navigator / libmocha * * This file contains common code for separate threads to send messages * to the mozilla thread to get it to do stuff */ #include "lm.h" #include "xp.h" #include "fe_proto.h" #include "net.h" #include "structs.h" #include "prthread.h" #include "prtypes.h" #include "prmem.h" #include "ds.h" /* XXX required by htmldlgs.h */ #include "htmldlgs.h" #include "layout.h" #include "np.h" #include "prefapi.h" #include "pa_parse.h" #include "libi18n.h" #include "netcache.h" #include "secnav.h" #define IL_CLIENT #include "libimg.h" /* Image Library public API. */ #define CHECKBOX_ACCEPTBIT 0x01 #define CHECKBOX_CHECKBIT 0x02 /* pointer to the mocha thread */ extern PRThread *mozilla_thread; /****************************************************************************/ PR_STATIC_CALLBACK(void*) et_PostEvent(ETEvent * e, Bool sync) { /* * Guard against the mozilla_event_queue goes away before we do * on exit. */ if(!mozilla_event_queue) return(NULL); /* * If we are already in the mozilla thread and about to send * a synchronous message to ourselves just process it right * now instead of deadlocking */ if(sync && PR_CurrentThread() == mozilla_thread) { void * val; val = e->event.handler(&e->event); e->event.destructor(&e->event); return(val); } if(sync) return(PR_PostSynchronousEvent(mozilla_event_queue, &e->event)); PR_PostEvent(mozilla_event_queue, &e->event); return(NULL); } /* * synchonous events can't be destroyed until after PR_PostSynchronousEvent() * has returned. This is a dummy destructor to make sure the event stays * alive along enough */ PR_STATIC_CALLBACK(void) et_DestroyEvent_WaitForIt(void * event) { } /* * Generic destructor for event with no private data */ PR_STATIC_CALLBACK(void) et_DestroyEvent_GenericEvent(void * event) { XP_FREE(event); } /****************************************************************************/ typedef struct { ETEvent ce; char* szMessage; /* message for dialog */ JSBool bConfirm; /* TRUE if confirmation, FALSE if alert */ } MozillaEvent_MessageBox; typedef struct { ETEvent ce; char* mainMessage, * checkMessage, * okMessage, * cancelMessage; JSBool accepted; /* dialog was OKed? */ XP_Bool checked; /* checkbox is checked? */ } MozillaEvent_CheckConfirmBox; /* CheckConfirm message box event */ PR_STATIC_CALLBACK(void*) et_HandleEvent_MessageBox(MozillaEvent_MessageBox* e) { void *pRet; Bool bPriorJSCalling = FALSE; if( e->ce.context ) { bPriorJSCalling = e->ce.context->bJavaScriptCalling; e->ce.context->bJavaScriptCalling = TRUE; } pRet = (void *)JSTYPE_BOOLEAN; if( e->bConfirm ) pRet = (void *)FE_Confirm(e->ce.context, e->szMessage); else FE_Alert(e->ce.context, e->szMessage); if( e->ce.context ) e->ce.context->bJavaScriptCalling = bPriorJSCalling; return pRet; } PR_STATIC_CALLBACK(void) et_DestroyEvent_MessageBox(MozillaEvent_MessageBox* event) { XP_FREE((char*)event->szMessage); XP_FREE(event); } PR_STATIC_CALLBACK(void*) et_HandleEvent_CheckConfirmBox(MozillaEvent_CheckConfirmBox* e) { void *pRet; Bool bPriorJSCalling = FALSE; if( e->ce.context ) { bPriorJSCalling = e->ce.context->bJavaScriptCalling; e->ce.context->bJavaScriptCalling = TRUE; } e->accepted = FE_CheckConfirm(e->ce.context, e->mainMessage, e->checkMessage, e->okMessage, e->cancelMessage, &e->checked); /* we're restricted to a single (void *) return value, and we need to return two separate booleans, thus the bit hackery: */ pRet = (void *) ((e->accepted ? CHECKBOX_ACCEPTBIT : 0x0) | (e->checked ? CHECKBOX_CHECKBIT : 0x0)); if( e->ce.context ) e->ce.context->bJavaScriptCalling = bPriorJSCalling; return pRet; } PR_STATIC_CALLBACK(void) et_DestroyEvent_CheckConfirmBox(MozillaEvent_CheckConfirmBox* event) { XP_FREE((char *)event->mainMessage); XP_FREE((void *)event->checkMessage); XP_FREEIF((void *)event->okMessage); XP_FREEIF((void *)event->cancelMessage); XP_FREE((void *)event); } JSBool ET_PostMessageBox(MWContext* context, char* szMessage, JSBool bConfirm) { JSBool ok = JS_TRUE; MozillaEvent_MessageBox* event = PR_NEW(MozillaEvent_MessageBox); if (event == NULL) return(JS_FALSE); event->ce.context = context; event->szMessage = strdup(szMessage); event->bConfirm = bConfirm; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_MessageBox, (PRDestroyEventProc)et_DestroyEvent_MessageBox); ok = (JSBool) et_PostEvent(&event->ce, TRUE); return(ok); } JSBool ET_PostCheckConfirmBox(MWContext* context, char* szMainMessage, char* szCheckMessage, char* szOKMessage, char* szCancelMessage, XP_Bool *bChecked) { uint8 rtnVal; MozillaEvent_CheckConfirmBox* event = PR_NEW(MozillaEvent_CheckConfirmBox); if (event == NULL) return JS_FALSE; event->ce.context = context; event->mainMessage = szMainMessage ? strdup(szMainMessage) : 0; event->checkMessage = szCheckMessage ? strdup(szCheckMessage) : 0; event->okMessage = szOKMessage ? strdup(szOKMessage) : 0; event->cancelMessage = szCancelMessage ? strdup(szCancelMessage) : 0; event->checked = *bChecked; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_CheckConfirmBox, (PRDestroyEventProc)et_DestroyEvent_CheckConfirmBox); rtnVal = (uint8) et_PostEvent(&event->ce, TRUE); *bChecked = (rtnVal & CHECKBOX_CHECKBIT) ? JS_TRUE : JS_FALSE; return (JSBool) (rtnVal & CHECKBOX_ACCEPTBIT) ? JS_TRUE : JS_FALSE; } /****************************************************************************/ typedef struct { ETEvent ce; const char * szMessage; /* progress message */ } MozillaEvent_Progress; PR_STATIC_CALLBACK(void) et_HandleEvent_Progress(MozillaEvent_Progress* e) { FE_Progress(e->ce.context, e->szMessage); } PR_STATIC_CALLBACK(void) et_DestroyEvent_Progress(MozillaEvent_MessageBox* event) { XP_FREE((char*)event->szMessage); XP_FREE(event); } void ET_PostProgress(MWContext* context, const char* szMessage) { MozillaEvent_Progress* event = PR_NEW(MozillaEvent_Progress); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_Progress, (PRDestroyEventProc)et_DestroyEvent_Progress); event->ce.context = context; if(szMessage) event->szMessage = strdup(szMessage); else event->szMessage = NULL; et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ typedef struct { ETEvent ce; void * pStuff; } MozillaEvent_Void; PR_STATIC_CALLBACK(void) et_HandleEvent_ClearTimeout(MozillaEvent_Void* e) { FE_ClearTimeout(e->pStuff); } void ET_PostClearTimeout(void * pStuff) { MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void); if (event == NULL) return; PR_InitEvent(&event->ce.event, NULL, (PRHandleEventProc)et_HandleEvent_ClearTimeout, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = NULL; event->pStuff = pStuff; et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ /* * OK, timeouts are messy. We are in a separate thread, we want to * call the mozilla thread to fire a timeout. When the timeout * fires we need to get a message sent back to our thread to call * our timeout since, presumably, our timeout needs to run in our * thread and not the mozilla thread. * Make a duplicate of the current event structure in case the * timeout gets fired and the 'run the closure' event gets sent * before we have returned from PR_PostSynchronousEvent(). */ PR_STATIC_CALLBACK(void*) et_HandleEvent_SetTimeout(MozillaEvent_Timeout* e) { MozillaEvent_Timeout* event = XP_NEW_ZAP(MozillaEvent_Timeout); if (event == NULL) return(NULL); event->fnCallback = e->fnCallback; event->pClosure = e->pClosure; event->ulTime = e->ulTime; event->ce.doc_id = e->ce.doc_id; event->ce.context = e->ce.context; event->pTimerId = FE_SetTimeout(ET_FireTimeoutCallBack, event, e->ulTime); return(event->pTimerId); } void * ET_PostSetTimeout(TimeoutCallbackFunction fnCallback, void * pClosure, uint32 ulTime, int32 doc_id) { MozillaEvent_Timeout* event = XP_NEW_ZAP(MozillaEvent_Timeout); void * ret; if (event == NULL) return(NULL); PR_InitEvent(&event->ce.event, NULL, (PRHandleEventProc)et_HandleEvent_SetTimeout, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.doc_id = doc_id; event->fnCallback = fnCallback; event->pClosure = pClosure; event->ulTime = ulTime; /* XXXMLM - pClosure appears to be an MWContext pointer in all the * instances I've seen. I'll use it for now. */ event->ce.context = (MWContext *) pClosure; ret = et_PostEvent(&event->ce, TRUE); return(ret); } typedef struct { ETEvent ce; int32 wrap_width; int32 parent_layer_id; } MozillaEvent_CreateLayer; PR_STATIC_CALLBACK(void*) et_HandleEvent_CreateLayer(MozillaEvent_CreateLayer * e) { int32 layer_id; /* See if the document has changed since this event was sent. */ if(e->ce.doc_id != XP_DOCID(e->ce.context)) return NULL; layer_id = LO_CreateNewLayer(e->ce.context, e->wrap_width, e->parent_layer_id); return (void*)layer_id; } int32 ET_PostCreateLayer(MWContext *context, int32 wrap_width, int32 parent_layer_id) { int32 ret; MozillaEvent_CreateLayer * event = XP_NEW_ZAP(MozillaEvent_CreateLayer); if (event == NULL) return(0); PR_InitEvent(&event->ce.event, NULL, (PRHandleEventProc)et_HandleEvent_CreateLayer, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->ce.doc_id = XP_DOCID(context); event->wrap_width = wrap_width; event->parent_layer_id = parent_layer_id; ret = (int32)et_PostEvent(&event->ce, TRUE); return(ret); } /****************************************************************************/ PR_STATIC_CALLBACK(void) et_HandleEvent_DestroyWindow(ETEvent* e) { e->context->waitingMode = FALSE; FE_DestroyWindow(e->context); } void ET_PostDestroyWindow(MWContext * context) { ETEvent * event = PR_NEW(ETEvent); if (event == NULL) return; PR_InitEvent(&event->event, context, (PRHandleEventProc)et_HandleEvent_DestroyWindow, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->context = context; et_PostEvent(event, FALSE); } /****************************************************************************/ typedef struct { ETEvent ce; LO_Element * pForm; int32 action; int32 docID; PRPackedBool duplicate; } MozillaEvent_ManipulateForm; PR_STATIC_CALLBACK(void) et_HandleEvent_ManipulateForm(MozillaEvent_ManipulateForm* e) { /* see if the document has changed since this event was sent */ if(e->docID != XP_DOCID(e->ce.context)) return; switch(e->action) { case EVENT_BLUR: FE_BlurInputElement(e->ce.context, e->pForm); break; case EVENT_FOCUS: FE_FocusInputElement(e->ce.context, e->pForm); break; case EVENT_SELECT: FE_SelectInputElement(e->ce.context, e->pForm); break; case EVENT_CLICK: FE_ClickInputElement(e->ce.context, e->pForm); break; case EVENT_CHANGE: FE_ChangeInputElement(e->ce.context, e->pForm); break; default: XP_ASSERT(0); } } PR_STATIC_CALLBACK(void) et_check_already_pending(MozillaEvent_ManipulateForm* event, MozillaEvent_ManipulateForm* data, PREventQueue* queue) { if (event->ce.event.owner == data->ce.event.owner) { if (event->action == data->action) data->duplicate = TRUE; } } void ET_PostManipulateForm(MWContext * context, LO_Element * pForm, int32 action) { MozillaEvent_ManipulateForm* event; event = PR_NEW(MozillaEvent_ManipulateForm); if (event == NULL) return; PR_InitEvent(&event->ce.event, pForm, (PRHandleEventProc)et_HandleEvent_ManipulateForm, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->docID = XP_DOCID(context); event->pForm = pForm; event->action = action; event->duplicate = FALSE; /* * Now that we have built the event use it to see if a similar * event already exists. If one does, the owner field will * get cleared in the event we just created */ PR_MapEvents(mozilla_event_queue, (PREventFunProc)et_check_already_pending, event); if (event->duplicate) { XP_FREE(event); return; } et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ PR_STATIC_CALLBACK(void) et_HandleEvent_ClearView(ETEvent * e) { FE_ClearView(e->context, FE_VIEW); } void ET_PostClearView(MWContext * context) { ETEvent * event = PR_NEW(ETEvent); if (event == NULL) return; PR_InitEvent(&event->event, context, (PRHandleEventProc)et_HandleEvent_ClearView, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->context = context; et_PostEvent(event, FALSE); } /****************************************************************************/ PR_STATIC_CALLBACK(void) et_HandleEvent_FreeImageElement(MozillaEvent_Void* e) { LO_ImageStruct *lo_image = (LO_ImageStruct *) e->pStuff; IL_DestroyImage(lo_image->image_req); lo_image->image_req = NULL; } /* * From the code flow it looked like some people were depending * on this getting done before continuing. Not sure if that * is really the case or not. Do we need to be synchronous? */ void ET_PostFreeImageElement(MWContext * context, void * pStuff) { MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_FreeImageElement, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->pStuff = pStuff; et_PostEvent(&event->ce, TRUE); } /****************************************************************************/ /* Free all images in the mocha image context. */ PR_STATIC_CALLBACK(void) et_HandleEvent_FreeAnonImages(MozillaEvent_Void* e) { IL_DestroyImageGroup((IL_GroupContext *)e->pStuff); } void ET_PostFreeAnonImages(MWContext *context, IL_GroupContext *img_cx) { MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_FreeAnonImages, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->pStuff = img_cx; et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ /* * Destroy the mocha image context in the Mozilla thread since * its destruction must succeed the actual destruction of * anonymous images. */ PR_STATIC_CALLBACK(void) et_HandleEvent_FreeImageContext(MozillaEvent_Void* e) { IL_DestroyGroupContext((IL_GroupContext *)e->pStuff); } void ET_PostFreeImageContext(MWContext *context, IL_GroupContext *img_cx) { MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_FreeImageContext, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->pStuff = img_cx; et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ PR_STATIC_CALLBACK(void) et_HandleEvent_GetUrl(MozillaEvent_Void* e) { FE_GetURL(e->ce.context, (URL_Struct *) e->pStuff); } void ET_PostGetUrl(MWContext * context, URL_Struct * pUrl) { MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_GetUrl, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->pStuff = pUrl; et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ typedef struct { ETEvent ce; char* szMessage; /* message for dialog */ char* szDefault; } MozillaEvent_Prompt; PR_STATIC_CALLBACK(void *) et_HandleEvent_Prompt(MozillaEvent_Prompt* e) { void *pRet; Bool bPriorJSCalling = FALSE; if( e->ce.context ) { bPriorJSCalling = e->ce.context->bJavaScriptCalling; e->ce.context->bJavaScriptCalling = TRUE; } pRet = (void *)FE_Prompt(e->ce.context, e->szMessage, e->szDefault); if( e->ce.context ) e->ce.context->bJavaScriptCalling = bPriorJSCalling; return pRet; } PR_STATIC_CALLBACK(void) et_DestroyEvent_Prompt(MozillaEvent_Prompt* event) { XP_FREE((char*)event->szMessage); XP_FREE((char*)event->szDefault); XP_FREE(event); } char * ET_PostPrompt(MWContext* context, const char* szMessage, const char * szDefault) { char * ret; MozillaEvent_Prompt* event = PR_NEW(MozillaEvent_Prompt); if (event == NULL) return(NULL); PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_Prompt, (PRDestroyEventProc)et_DestroyEvent_Prompt); event->ce.context = context; event->szMessage = strdup(szMessage); if(szDefault) event->szDefault = strdup(szDefault); else event->szDefault = NULL; ret = (char *) et_PostEvent(&event->ce, TRUE); return(ret); } /****************************************************************************/ typedef struct { ETEvent ce; URL_Struct * pUrl; char * szName; Chrome * pChrome; LMWindowGroup * group; } MozillaEvent_NewWindow; PR_STATIC_CALLBACK(void*) et_HandleEvent_NewWindow(MozillaEvent_NewWindow* e) { LMWindowGroup *grp = e->group; MWContext *ans = FE_MakeNewWindow(e->ce.context, e->pUrl, e->szName, e->pChrome); if(grp != NULL) { LM_AddContextToGroup(grp, ans); } return (void *) ans; } PR_STATIC_CALLBACK(void) et_DestroyEvent_NewWindow(MozillaEvent_NewWindow* event) { NET_DropURLStruct(event->pUrl); if (event->szName) XP_FREE((char*)event->szName); XP_FREE(event); } MWContext * ET_PostNewWindow(MWContext* context, URL_Struct * pUrl, char * szName, Chrome * pChrome, LMWindowGroup *grp) { MWContext * ret; MozillaEvent_NewWindow* event = PR_NEW(MozillaEvent_NewWindow); if (event == NULL) return(NULL); PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_NewWindow, (PRDestroyEventProc)et_DestroyEvent_NewWindow); event->ce.context = context; event->pUrl = NET_HoldURLStruct(pUrl); if(szName) event->szName = strdup(szName); else event->szName = NULL; event->pChrome = pChrome; event->group = grp; ret = (MWContext *) et_PostEvent(&event->ce, TRUE); return(ret); } /****************************************************************************/ typedef struct { ETEvent ce; Chrome * pChrome; } MozillaEvent_UpdateWindow; PR_STATIC_CALLBACK(void) et_HandleEvent_UpdateWindow(MozillaEvent_UpdateWindow* e) { FE_UpdateChrome(e->ce.context, e->pChrome); } void ET_PostUpdateChrome(MWContext* context, Chrome * pChrome) { MozillaEvent_UpdateWindow* event = PR_NEW(MozillaEvent_UpdateWindow); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_UpdateWindow, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->pChrome = pChrome; et_PostEvent(&event->ce, TRUE); } /****************************************************************************/ typedef struct { ETEvent ce; Chrome * pChrome; } MozillaEvent_QueryWindow; PR_STATIC_CALLBACK(void) et_HandleEvent_QueryWindow(MozillaEvent_QueryWindow* e) { FE_QueryChrome(e->ce.context, e->pChrome); } void ET_PostQueryChrome(MWContext* context, Chrome * pChrome) { MozillaEvent_QueryWindow* event = PR_NEW(MozillaEvent_QueryWindow); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_QueryWindow, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->pChrome = pChrome; et_PostEvent(&event->ce, TRUE); } /****************************************************************************/ typedef struct { ETEvent ce; int32 *pPixel; int32 *pPallette; } MozillaEvent_GetColorDepth; PR_STATIC_CALLBACK(void) et_HandleEvent_GetColorDepth(MozillaEvent_GetColorDepth* e) { FE_GetPixelAndColorDepth(e->ce.context, e->pPixel, e->pPallette); } void ET_PostGetColorDepth(MWContext* context, int32 *pPixel, int32 *pPallette) { int32 *pMPixel = NULL, *pMPallette = NULL; MozillaEvent_GetColorDepth* event = PR_NEW(MozillaEvent_GetColorDepth); if (event == NULL) return; pMPixel = XP_ALLOC(sizeof(int32)); if (pMPixel == NULL) goto fail; pMPallette = XP_ALLOC(sizeof(int32)); if (pMPallette == NULL) goto fail; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_GetColorDepth, (PRDestroyEventProc)et_DestroyEvent_WaitForIt); event->ce.context = context; event->pPixel = pMPixel; event->pPallette = pMPallette; et_PostEvent(&event->ce, TRUE); *pPixel = *event->pPixel; *pPallette = *event->pPallette; fail: if (pMPixel) XP_FREE(pMPixel); if (pMPallette) XP_FREE(pMPallette); if (event) XP_FREE(event); } /****************************************************************************/ typedef struct { ETEvent ce; int32 *pX; int32 *pY; } MozillaEvent_GetScreenSize; PR_STATIC_CALLBACK(void) et_HandleEvent_GetScreenSize(MozillaEvent_GetScreenSize* e) { FE_GetScreenSize(e->ce.context, e->pX, e->pY); } void ET_PostGetScreenSize(MWContext* context, int32 *pX, int32 *pY) { int32 *pMX = NULL, *pMY = NULL; MozillaEvent_GetScreenSize* event = PR_NEW(MozillaEvent_GetScreenSize); if (event == NULL) return; pMX = XP_ALLOC(sizeof(int32)); if (pMX == NULL) goto fail; pMY = XP_ALLOC(sizeof(int32)); if (pMY == NULL) goto fail; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_GetScreenSize, (PRDestroyEventProc)et_DestroyEvent_WaitForIt); event->ce.context = context; event->pX = pMX; event->pY = pMY; et_PostEvent(&event->ce, TRUE); *pX = *event->pX; *pY = *event->pY; fail: if (pMX) XP_FREE(pMX); if (pMY) XP_FREE(pMY); if (event) XP_FREE(event); } /****************************************************************************/ typedef struct { ETEvent ce; int32 *pX; int32 *pY; int32 *pLeft; int32 *pTop; } MozillaEvent_GetAvailScreenRect; PR_STATIC_CALLBACK(void) et_HandleEvent_GetAvailScreenRect(MozillaEvent_GetAvailScreenRect* e) { FE_GetAvailScreenRect(e->ce.context, e->pX, e->pY, e->pLeft, e->pTop); } void ET_PostGetAvailScreenRect(MWContext* context, int32 *pX, int32 *pY, int32 *pLeft, int32 *pTop) { int32 *pMX = NULL, *pMY = NULL, *pMLeft = NULL, *pMTop = NULL; MozillaEvent_GetAvailScreenRect* event = PR_NEW(MozillaEvent_GetAvailScreenRect); if (event == NULL) return; pMX = XP_ALLOC(sizeof(int32)); if (pMX == NULL) goto fail; pMY = XP_ALLOC(sizeof(int32)); if (pMY == NULL) goto fail; pMLeft = XP_ALLOC(sizeof(int32)); if (pMLeft == NULL) goto fail; pMTop = XP_ALLOC(sizeof(int32)); if (pMTop == NULL) goto fail; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_GetAvailScreenRect, (PRDestroyEventProc)et_DestroyEvent_WaitForIt); event->ce.context = context; event->pX = pMX; event->pY = pMY; event->pLeft = pMLeft; event->pTop = pMTop; et_PostEvent(&event->ce, TRUE); *pX = *event->pX; *pY = *event->pY; *pLeft = *event->pLeft; *pTop = *event->pTop; fail: if (pMX) XP_FREE(pMX); if (pMY) XP_FREE(pMY); if (pMLeft) XP_FREE(pMLeft); if (pMTop) XP_FREE(pMTop); if (event) XP_FREE(event); } /****************************************************************************/ typedef struct { ETEvent ce; char * szText; } MozillaEvent_GetSelectedText; PR_STATIC_CALLBACK(void*) et_HandleEvent_GetSelectedText(MozillaEvent_GetSelectedText* e) { char * rv; rv = (char *)LO_GetSelectionText(e->ce.context); if (rv) rv = XP_STRDUP(rv); return rv; } char * ET_PostGetSelectedText(MWContext* context) { char * ret; MozillaEvent_GetSelectedText* event = XP_NEW_ZAP(MozillaEvent_GetSelectedText); if (event == NULL) return(NULL); PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_GetSelectedText, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; ret = (char *) et_PostEvent(&event->ce, TRUE); return(ret); } /****************************************************************************/ typedef struct { ETEvent ce; int location; int32 x, y; } MozillaEvent_ScrollTo; PR_STATIC_CALLBACK(void) et_HandleEvent_ScrollTo(MozillaEvent_ScrollTo* e) { FE_ScrollDocTo(e->ce.context, e->location, e->x, e->y); } void ET_PostScrollDocTo(MWContext* context, int loc, int32 x, int32 y) { MozillaEvent_ScrollTo* event = PR_NEW(MozillaEvent_ScrollTo); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_ScrollTo, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->location = loc; event->x = x; event->y = y; et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ typedef struct { ETEvent ce; int location; int32 x, y; } MozillaEvent_ScrollBy; PR_STATIC_CALLBACK(void) et_HandleEvent_ScrollBy(MozillaEvent_ScrollBy* e) { FE_ScrollDocBy(e->ce.context, e->location, e->x, e->y); } void ET_PostScrollDocBy(MWContext* context, int loc, int32 x, int32 y) { MozillaEvent_ScrollBy* event = PR_NEW(MozillaEvent_ScrollBy); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_ScrollBy, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->location = loc; event->x = x; event->y = y; et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ PR_STATIC_CALLBACK(void) et_HandleEvent_BackCommand(ETEvent* e) { FE_BackCommand(e->context); } void ET_PostBackCommand(MWContext* context) { ETEvent* event = PR_NEW(ETEvent); if (event == NULL) return; PR_InitEvent(&event->event, context, (PRHandleEventProc)et_HandleEvent_BackCommand, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->context = context; et_PostEvent(event, FALSE); } /****************************************************************************/ typedef struct { ETEvent ce; } MozillaEvent_ForwardCommand; PR_STATIC_CALLBACK(void) et_HandleEvent_ForwardCommand(ETEvent* e) { FE_ForwardCommand(e->context); } void ET_PostForwardCommand(MWContext* context) { ETEvent* event = PR_NEW(ETEvent); if (event == NULL) return; PR_InitEvent(&event->event, context, (PRHandleEventProc)et_HandleEvent_ForwardCommand, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->context = context; et_PostEvent(event, FALSE); } /****************************************************************************/ PR_STATIC_CALLBACK(void) et_HandleEvent_HomeCommand(ETEvent* e) { FE_HomeCommand(e->context); } void ET_PostHomeCommand(MWContext* context) { ETEvent* event = PR_NEW(ETEvent); if (event == NULL) return; PR_InitEvent(&event->event, context, (PRHandleEventProc)et_HandleEvent_HomeCommand, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->context = context; et_PostEvent(event, FALSE); } /****************************************************************************/ typedef struct { ETEvent ce; char * szName; XP_Bool matchCase; XP_Bool searchBackward; } MozillaEvent_FindCommand; PR_STATIC_CALLBACK(void*) et_HandleEvent_FindCommand(MozillaEvent_FindCommand* e) { return(void *)FE_FindCommand(e->ce.context, e->szName, e->matchCase, e->searchBackward, FALSE); } PR_STATIC_CALLBACK(void) et_DestroyEvent_FindCommand(MozillaEvent_FindCommand* event) { if(event->szName) XP_FREE((char*)event->szName); XP_FREE(event); } JSBool ET_PostFindCommand(MWContext* context, char *szName, JSBool matchCase, JSBool searchBackward) { JSBool ret; MozillaEvent_FindCommand* event = PR_NEW(MozillaEvent_FindCommand); if (event == NULL) return JS_FALSE; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_FindCommand, (PRDestroyEventProc)et_DestroyEvent_FindCommand); event->ce.context = context; if(szName) event->szName = strdup(szName); else event->szName = NULL; event->matchCase = (XP_Bool)matchCase; event->searchBackward = (XP_Bool)searchBackward; ret = (JSBool)et_PostEvent(&event->ce, TRUE); return(ret); } /****************************************************************************/ typedef struct { ETEvent ce; } MozillaEvent_PrintCommand; PR_STATIC_CALLBACK(void) et_HandleEvent_PrintCommand(ETEvent* e) { FE_PrintCommand(e->context); } void ET_PostPrintCommand(MWContext* context) { ETEvent* event = PR_NEW(ETEvent); if (event == NULL) return; PR_InitEvent(&event->event, context, (PRHandleEventProc)et_HandleEvent_PrintCommand, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->context = context; et_PostEvent(event, FALSE); } /****************************************************************************/ PR_STATIC_CALLBACK(void) et_HandleEvent_OpenFileCommand(ETEvent* e) { } void ET_PostOpenFileCommand(MWContext* context) { ETEvent* event = PR_NEW(ETEvent); if (event == NULL) return; PR_InitEvent(&event->event, context, (PRHandleEventProc)et_HandleEvent_OpenFileCommand, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->context = context; et_PostEvent(event, FALSE); } /****************************************************************************/ typedef struct { ETEvent ce; char* szMessage; /* message for dialog */ } MozillaEvent_HtmlAlert; PR_STATIC_CALLBACK(void) et_HandleEvent_HtmlAlert(MozillaEvent_HtmlAlert* e) { XP_MakeHTMLAlert(e->ce.context, e->szMessage); } PR_STATIC_CALLBACK(void) et_DestroyEvent_HtmlAlert(MozillaEvent_HtmlAlert* event) { XP_FREE((char*)event->szMessage); XP_FREE(event); } void ET_MakeHTMLAlert(MWContext* context, const char* szMessage) { MozillaEvent_HtmlAlert* event = PR_NEW(MozillaEvent_HtmlAlert); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_HtmlAlert, (PRDestroyEventProc)et_DestroyEvent_HtmlAlert); event->ce.context = context; event->szMessage = strdup(szMessage); et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ typedef struct { ETEvent ce; LO_Element * pEle; int type; ETClosureFunc fnClosure; void * pStuff; ETEventStatus status; } MozillaEvent_JsEventAck; PR_STATIC_CALLBACK(void) et_HandleEvent_JsEventAck(MozillaEvent_JsEventAck* e) { /* make sure we haven't gone away somehow */ if(e->ce.doc_id != XP_DOCID(e->ce.context)) e->status = EVENT_PANIC; (*e->fnClosure) (e->ce.context, e->pEle, e->type, e->pStuff, e->status); } void ET_PostJsEventAck(MWContext* context, LO_Element * pEle, int type, ETClosureFunc fnClosure, void * pStuff, ETEventStatus status) { MozillaEvent_JsEventAck* event = PR_NEW(MozillaEvent_JsEventAck); if (event == NULL) return; PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_JsEventAck, (PRDestroyEventProc)et_DestroyEvent_GenericEvent); event->ce.context = context; event->ce.doc_id = XP_DOCID(context); event->pEle = pEle; event->type = type; event->fnClosure = fnClosure; event->pStuff = pStuff; event->status = status; et_PostEvent(&event->ce, FALSE); } /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ typedef struct { ETEvent ce; FO_Present_Types format; URL_Struct * pUrl; void * pStuff; uint32 ulBytes; } MozillaEvent_GenericNetLib; PR_STATIC_CALLBACK(void*) et_HandleEvent_CacheConverter(MozillaEvent_GenericNetLib* e) { void *retval = (void *)NET_CacheConverter(e->format, e->pStuff, e->pUrl, e->ce.context); return retval; } PR_STATIC_CALLBACK(void) et_DestroyEvent_NetlibWithUrl(MozillaEvent_GenericNetLib* e) { NET_DropURLStruct(e->pUrl); XP_FREE(e); } NET_StreamClass * ET_net_CacheConverter(FO_Present_Types format, void * obj, URL_Struct *pUrl, MWContext * context) { NET_StreamClass * ret; MozillaEvent_GenericNetLib* event = PR_NEW(MozillaEvent_GenericNetLib); if (event == NULL) return(NULL); PR_InitEvent(&event->ce.event, context, (PRHandleEventProc)et_HandleEvent_CacheConverter, (PRDestroyEventProc)et_DestroyEvent_NetlibWithUrl); event->ce.context = context; event->format = format; event->pStuff = obj; event->pUrl = NET_HoldURLStruct(pUrl); ret = (NET_StreamClass *) et_PostEvent(&event->ce, TRUE); return(ret); } /****************************************************************************/ PR_STATIC_CALLBACK(void) et_HandleEvent_FindURLInCache(MozillaEvent_GenericNetLib* e) { NET_FindURLInCache(e->pUrl, e->ce.context); } /* NOTE: as far as libmocha is concerned, we just need this routine to complete. We don't care about the return value */ void ET_net_FindURLInCache(URL_Struct * pUrl, MWContext * pContext) { MozillaEvent_GenericNetLib* event = PR_NEW(MozillaEvent_GenericNetLib); if (event == NULL) return; PR_InitEvent(&event->ce.event, pContext, (PRHandleEventProc)et_HandleEvent_FindURLInCache, (PRDestroyEventProc)et_DestroyEvent_NetlibWithUrl); event->ce.context = pContext; event->pUrl = NET_HoldURLStruct(pUrl); et_PostEvent(&event->ce, TRUE); } /****************************************************************************/ PR_STATIC_CALLBACK(void*) et_HandleEvent_StreamBuilder(MozillaEvent_GenericNetLib* e) { NET_StreamClass *rv; NET_SetActiveEntryBusyStatus(e->pUrl, TRUE); rv = NET_StreamBuilder(e->format, e->pUrl, e->ce.context); NET_SetActiveEntryBusyStatus(e->pUrl, FALSE); return((void *)rv); } NET_StreamClass * ET_net_StreamBuilder(FO_Present_Types format, URL_Struct *pUrl, MWContext * pContext) { NET_StreamClass * ret; MozillaEvent_GenericNetLib* event = PR_NEW(MozillaEvent_GenericNetLib); if (event == NULL) return(NULL); PR_InitEvent(&event->ce.event, pContext, (PRHandleEventProc)et_HandleEvent_StreamBuilder, (PRDestroyEventProc)et_DestroyEvent_NetlibWithUrl); event->ce.context = pContext; event->format = format; event->pUrl = NET_HoldURLStruct(pUrl); ret = (NET_StreamClass *) et_PostEvent(&event->ce, TRUE); return(ret); } /****************************************************************************/ typedef struct { ETEvent ce; NET_StreamClass * stream; void * data; size_t len; JSBool self_modifying; JSBool processed; } MozillaEvent_DocWrite; /* * A lot of this should get moved out to the layout module * I don't think we need to bother locking layout in this function * since we are running in the mozilla thread and the mocha * thread is blocked waiting for our return value. */ PR_STATIC_CALLBACK(void*) et_HandleEvent_DocWrite(MozillaEvent_DocWrite* e) { lo_TopState *top_state; int32 pre_doc_id; LO_Element * save_blocking = NULL; LO_Element * current_script = NULL; Bool bumped_no_newline_count = FALSE; uint save_overflow=0; int status; e->processed = JS_TRUE; /* * If the context has a doc_id of -1 it means that its being destroyed * If the context's doc_id has changed only process the event if the * original doc_id was zero (i.e. this is the first write and it will * create a new doc with a new doc_id) */ pre_doc_id = XP_DOCID(e->ce.context); if ((e->ce.doc_id && e->ce.doc_id != pre_doc_id) || (pre_doc_id == -1)) { #ifdef DEBUG_chouck XP_TRACE(("Ignoring doc.write since doc_id changed")); #endif ET_DocWriteAck(e->ce.context, -1); return((void *) -1); } if (!ET_ContinueProcessing(e->ce.context)) { #ifdef DEBUG_chouck XP_TRACE(("Ignoring doc.write since was interrupted")); #endif ET_DocWriteAck(e->ce.context, -1); return((void *) -1); } /* make sure top_state doesn't go away while we are holding onto it */ LO_LockLayout(); top_state = lo_GetMochaTopState(e->ce.context); /* tell layout that we are writing */ if (top_state) { if (top_state->input_write_level >= MAX_INPUT_WRITE_LEVEL-1) { LO_UnlockLayout(); ET_DocWriteAck(e->ce.context, -1); return ((void *) -1); } top_state->input_write_level++; if (top_state->doc_data) { /* Suppress generated line counting if self-modifying. */ if (e->self_modifying) { top_state->doc_data->no_newline_count++; bumped_no_newline_count = TRUE; } /* Save the overflow counter and XXX */ save_overflow = top_state->doc_data->overflow_depth; top_state->doc_data->overflow_depth = 0; } else { save_overflow = 0; } current_script = top_state->current_script; /* * if we are currently blocked by a