1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936 |
- /* -*- Mode: C; tab-width: 4; -*- */
- /* npmngplg.c
- * MNG browser plugin
- * By Jason Summers
- * Based on libmng by Gerard Juyn
- */
- #include <windows.h>
- #include <commdlg.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <stdarg.h>
- #include "resource.h"
- #include "libmng.h"
- #include "jversion.h" // part of libjpeg
- #include "zlib.h" // for zlibVersion
- #include "npapidefs.h"
- #define MNGPLG_CMS
- //#define MNGPLG_TRACE
- #define IDBASE 47000
- #define ID_SAVEAS (IDBASE+0)
- #define ID_COPYIMAGE (IDBASE+1)
- #define ID_COPYURL (IDBASE+2)
- #define ID_VIEWIMAGE (IDBASE+3)
- #define ID_ABOUT (IDBASE+4)
- #define ID_FREEZE (IDBASE+5)
- #define ID_RESTARTANIM (IDBASE+6)
- #define ID_COPYLINKLOC (IDBASE+7)
- #define ID_STOPANIM (IDBASE+8)
- #define ID_SHOWERROR (IDBASE+9)
- #define ID_PROPERTIES (IDBASE+10)
- #define MNGPLGVERS "1.0.1"
- /* instance-specific data */
- typedef struct pluginstruct_
- {
- NPWindow* fWindow;
- uint16 fMode;
- HWND fhWnd;
- WNDPROC fDefaultWindowProc;
- NPP instance;
- mng_handle mng;
- #define STATE_INIT 0
- #define STATE_LOADING 1 // stream opened
- #define STATE_VALIDFRAME 2 // at least one frame has been displayed
- #define STATE_LOADED 3 // image loaded; stream closed
- #define MAXLEN_TEXT 5000
- #define MAXLEN_URL 300
- #define MAXLEN_TARGET 100
- // I think I'm not doing this very well. Probably there really needs to be
- // two state variables, one for loading from the network, and one for
- // the libmng processing. (or use libmng's new getstate API?)
- int loadstate;
- int paintedyet;
- int scrolling; // allow scrolling of the image?
- int xscrollpos, yscrollpos;
- int windowwidth, windowheight; // client size of current window
- int diblinesize;
- DWORD dibsize;
- DWORD filesize;
- DWORD libmngpos; // count of bytes that have been sent to libmng
- DWORD byteswanted; // libmng asked for this many more bytes (add to libmngpos)
- unsigned char *mngdata; // stores the MNG file in memory
- DWORD bytesloaded; //
- DWORD bytesalloc; // size of mngdata
- int needresume; // if previous mng_readdisplay call returned NEEDMOREDATA
- char *textdata;
- int errorflag; // set if an error occurs that prevents displaying the image
- char errormsg[256];
- unsigned char *lpdib; // pointer to header section of dib
- unsigned char *lpdibbits; // pointer to "bits" section of dib (follows the header)
- LPBITMAPINFOHEADER lpdibinfo; // alias for lpdib
- int frozen;
- int timer_set;
- int timer2_set;
- int dynamicmng;
- int mouse_over_mng;
- int mouse_captured;
- int force_bgcolor;
- mng_uint16 bg_r,bg_g,bg_b; // background color
- unsigned char url[MAX_PATH]; // the url of the stream
- int islink;
- HCURSOR linkcursor;
- HBRUSH bkgdbrush;
- unsigned char linkurl[MAXLEN_URL];
- unsigned char linktarget[MAXLEN_TARGET];
- } PluginInstance;
- /* global variables */
- #ifdef MNGPLG_TRACE
- static FILE *tracefile;
- #endif
- static const char* gInstanceLookupString = "pdata";
- static HMODULE g_hInst = NULL;
- static HCURSOR hcurHandNS;
- static HFONT hfontMsg;
- /* function prototypes */
- LRESULT CALLBACK DlgProcAbout(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
- LRESULT CALLBACK DlgProcProp(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
- LRESULT CALLBACK PluginWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
- void set_scrollbars(PluginInstance *This);
- //////////////////////////// NPN_functions
- static NPNetscapeFuncs* g_pNavigatorFuncs;
- static NPPluginFuncs* g_pluginFuncs;
- static const char* NPN_UserAgent(NPP instance)
- {
- return g_pNavigatorFuncs->uagent(instance);
- }
- static NPError NPN_GetURL(NPP instance, const char *url, const char *target)
- {
- return g_pNavigatorFuncs->geturl(instance, url, target);
- }
- /* ----------------------------------------------------------------------- */
- BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved)
- {
- switch(reason) {
- case DLL_PROCESS_ATTACH:
- g_hInst=hModule;
- break;
- case DLL_THREAD_ATTACH:
- break;
- case DLL_THREAD_DETACH:
- break;
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
- }
- /* ----------------------------------------------------------------------- */
- static void warn(PluginInstance *This, char *fmt, ...)
- {
- va_list ap;
- char buf[2048];
- HWND hwnd;
- va_start(ap, fmt);
- wvsprintf(buf,fmt, ap);
- va_end(ap);
- if(This) hwnd= This->fhWnd;
- else hwnd=NULL;
- MessageBox(hwnd,buf,"MNG Plug-in",MB_OK|MB_ICONWARNING);
- }
- static void set_error(PluginInstance *This, char *fmt, ...)
- {
- va_list ap;
- char buf[2048];
- HWND hwnd;
- va_start(ap, fmt);
- wvsprintf(buf,fmt, ap);
- va_end(ap);
- if(This) hwnd= This->fhWnd;
- else hwnd=NULL;
- This->errorflag=1;
- lstrcpyn(This->errormsg,buf,256);
- if(This->lpdib) {
- free(This->lpdib);
- This->lpdib=NULL;
- }
- This->xscrollpos = This->yscrollpos = 0;
- if(This->fhWnd)
- InvalidateRect(This->fhWnd,NULL,TRUE);
- }
- /* ----------------------------------------------------------------------- */
- // MNG callbacks
- #define MNGPLG_CALLBACK MNG_DECL
- static mng_ptr MNGPLG_CALLBACK memallocfunc(mng_size_t n)
- {
- return (mng_ptr) calloc(n,1);
- }
- static void MNGPLG_CALLBACK memfreefunc(mng_ptr p, mng_size_t n)
- {
- free((void*)p);
- }
- static mng_bool MNGPLG_CALLBACK callback_openstream (mng_handle mng)
- {
- // PluginInstance *This;
- // This = (PluginInstance*) mng_get_userdata(mng);
- return MNG_TRUE;
- }
- static mng_bool MNGPLG_CALLBACK callback_closestream (mng_handle mng)
- {
- PluginInstance *This;
- This = (PluginInstance*) mng_get_userdata(mng);
- This->loadstate = STATE_LOADED; // this is probably redundant
- return MNG_TRUE;
- }
- static mng_bool MNGPLG_CALLBACK callback_readdata (mng_handle mng,mng_ptr pBuf,
- mng_uint32 Buflen,mng_uint32 *pRead)
- {
- int n;
- PluginInstance *This;
- This = (PluginInstance*) mng_get_userdata(mng);
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"readdata callback buflen=%d loadstate=%d bytesloaded=%d libmngpos=%d\n",
- Buflen,This->loadstate,This->bytesloaded, This->libmngpos);
- #endif
- // do we have enough data available?
- if(This->bytesloaded - This->libmngpos >= Buflen) {
- CopyMemory(pBuf,&This->mngdata[This->libmngpos],Buflen);
- (*pRead)= Buflen;
- This->libmngpos += Buflen;
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"returning full: %d\n",Buflen);
- #endif
- This->byteswanted=0;
- return MNG_TRUE;
- }
- else if(This->loadstate>=STATE_LOADED) {
- // We don't have the data it asked for, but we're at the end
- // of file, so send it anyway...?
- n=This->bytesloaded-This->libmngpos;
- if(n>0) {
- CopyMemory(pBuf,&This->mngdata[This->libmngpos],n);
- This->libmngpos+=n;
- }
- (*pRead)=n;
- // so what do we return?
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"returning partial: %d\n",n);
- #endif
- This->byteswanted=0;
- return MNG_TRUE;
- }
- // else we don't yet have the data it's requesting
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"returning 0\n");
- #endif
- (*pRead)=0;
- This->byteswanted=Buflen;
- return MNG_TRUE;
- }
- static mng_bool MNGPLG_CALLBACK callback_processheader(mng_handle mng,mng_uint32 iWidth,mng_uint32 iHeight)
- {
- PluginInstance *This;
- This = (PluginInstance*) mng_get_userdata(mng);
- This->diblinesize = (((iWidth * 24)+31)/32)*4;
- This->dibsize = sizeof(BITMAPINFOHEADER) + This->diblinesize*iHeight;
- This->lpdib = calloc(This->dibsize,1);
- This->lpdibinfo = (LPBITMAPINFOHEADER)This->lpdib;
- This->lpdibbits = &This->lpdib[sizeof(BITMAPINFOHEADER)];
- ZeroMemory((void*)This->lpdib,sizeof(BITMAPINFOHEADER));
- This->lpdibinfo->biSize = sizeof(BITMAPINFOHEADER);
- This->lpdibinfo->biWidth = iWidth;
- This->lpdibinfo->biHeight = iHeight;
- This->lpdibinfo->biPlanes = 1;
- This->lpdibinfo->biBitCount = 24;
- mng_set_canvasstyle (mng, MNG_CANVAS_BGR8);
- /* if(This->fhWnd) {
- if((int)iWidth > This->windowwidth || (int)iHeight > This->windowheight) {
- This->scrolling=1;
- }
- } */
- set_scrollbars(This);
- return MNG_TRUE;
- }
- static mng_ptr MNGPLG_CALLBACK callback_getcanvasline (mng_handle mng, mng_uint32 iLinenr)
- {
- unsigned char *pp;
- PluginInstance *This;
- This = (PluginInstance*) mng_get_userdata(mng);
- pp = (&This->lpdibbits[(This->lpdibinfo->biHeight-1-iLinenr)*This->diblinesize]);
- return (mng_ptr) pp;
- }
- static mng_bool MNGPLG_CALLBACK callback_refresh (mng_handle mng, mng_uint32 iLeft, mng_uint32 iTop,
- mng_uint32 iRight, mng_uint32 iBottom)
- {
- PluginInstance *This;
- RECT rect;
- This = (PluginInstance*) mng_get_userdata(mng);
- if(This->loadstate<STATE_VALIDFRAME) {
- This->loadstate=STATE_VALIDFRAME;
- }
- if(This->fhWnd) {
- if(This->paintedyet) {
- rect.left= iLeft - This->xscrollpos;
- rect.top= iTop - This->yscrollpos;
- rect.right= iLeft+iRight;
- rect.bottom= iTop+iBottom;
- InvalidateRect(This->fhWnd,&rect,FALSE);
- }
- else {
- // Make sure the first paint clears the whole plugin window
- InvalidateRect(This->fhWnd,NULL,TRUE);
- This->paintedyet=1;
- }
- UpdateWindow(This->fhWnd);
- }
- return MNG_TRUE;
- }
- static mng_uint32 MNGPLG_CALLBACK callback_gettickcount (mng_handle mng)
- {
- return GetTickCount();
- }
- static mng_bool MNGPLG_CALLBACK callback_settimer (mng_handle mng,mng_uint32 iMsecs)
- {
- PluginInstance *This;
- This = (PluginInstance*) mng_get_userdata(mng);
- if(This->fhWnd) {
- if(!SetTimer(This->fhWnd,1,(UINT)iMsecs,NULL)) {
- warn(This,"Unable to create a timer for animation");
- This->frozen=1;
- //return MNG_FALSE;
- return MNG_TRUE;
- }
- This->timer_set=1;
- }
- return MNG_TRUE;
- }
- static mng_bool MNGPLG_CALLBACK callback_processtext(mng_handle mng,
- mng_uint8 iType, mng_pchar zKeyword, mng_pchar zText,
- mng_pchar zLanguage, mng_pchar zTranslation)
- {
- PluginInstance *This;
- int pos,i;
- This = (PluginInstance*) mng_get_userdata(mng);
- if(!This->textdata) {
- This->textdata=(char*)malloc(MAXLEN_TEXT+10);
- if(!This->textdata) return MNG_TRUE;
- lstrcpy(This->textdata,"");
- }
- pos=lstrlen(This->textdata);
- if(pos>=(MAXLEN_TEXT-10)) return MNG_TRUE;
- if(pos>0) { /* separate items with a blank line */
- This->textdata[pos++]='\r';
- This->textdata[pos++]='\n';
- This->textdata[pos++]='\r';
- This->textdata[pos++]='\n';
- }
- for(i=0;zKeyword[i];i++) {
- if(pos<MAXLEN_TEXT)
- This->textdata[pos++]=zKeyword[i];
- }
- This->textdata[pos++]=':';
- This->textdata[pos++]=' ';
- for(i=0;zText[i];i++) {
- if(pos<MAXLEN_TEXT) {
- if(zText[i]=='\n') {
- This->textdata[pos++]='\r';
- }
- This->textdata[pos++]=zText[i];
- }
- }
- This->textdata[pos++]='\0';
- return MNG_TRUE;
- }
- #ifdef MNGPLG_TRACE
- static mng_bool MNGPLG_CALLBACK callback_traceproc (mng_handle mng,
- mng_int32 iFuncnr,
- mng_int32 iFuncseq,
- mng_pchar zFuncname)
- {
- if(tracefile) {
- fprintf(tracefile,"%d\t%d\t%d\t%s\n",(int)mng,iFuncnr,iFuncseq,zFuncname);
- }
- return MNG_TRUE;
- }
- #endif
- /* ----------------------------------------------------------------------- */
- static int file_exists(const char *fn)
- {
- HANDLE h;
- // try to open with no access
- h=CreateFile(fn,0,FILE_SHARE_READ,NULL,OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,NULL);
- if(h == INVALID_HANDLE_VALUE) { return 0; }
- CloseHandle(h);
- return 1;
- }
- static void handle_read_error(PluginInstance *This, mng_retcode rv)
- {
- mng_int8 iSeverity;
- mng_chunkid iChunkname;
- mng_uint32 iChunkseq;
- mng_int32 iExtra1;
- mng_int32 iExtra2;
- mng_pchar zErrortext;
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"returned: %d\n",rv);
- #endif
- switch(rv) {
- case MNG_NOERROR: case MNG_NEEDTIMERWAIT:
- break;
- case MNG_NEEDMOREDATA:
- if(This->loadstate>=STATE_LOADED) {
- set_error(This,"Unexpected end of file");
- }
- else {
- This->needresume=1;
- }
- break;
- case MNG_INVALIDSIG:
- set_error(This,"Invalid or missing MNG file (maybe a 404 Not Found error)");
- break;
- default:
- mng_getlasterror(This->mng, &iSeverity,&iChunkname,&iChunkseq,&iExtra1,
- &iExtra2,&zErrortext);
- if(zErrortext) {
- set_error(This,"Error reported by libmng (%d)\r\n\r\n%s",(int)rv,zErrortext);
- }
- else {
- set_error(This,"Error %d reported by libmng",(int)rv);
- }
- }
- }
- #ifdef MNGPLG_CMS
- static int init_color_management(PluginInstance *This)
- {
- mng_set_outputsrgb(This->mng);
- return 1;
- }
- #endif
- // return 1 if okay
- static int my_init_mng(PluginInstance *This)
- {
- mng_retcode rv;
- int err;
- This->mng = mng_initialize((mng_ptr)This,memallocfunc,memfreefunc,NULL);
- //(mng_memalloc) (mng_memfree)
- #ifdef MNGPLG_CMS
- init_color_management(This);
- #endif
- err=0;
- rv=mng_setcb_openstream (This->mng, callback_openstream ); if(rv) err++;
- rv=mng_setcb_closestream (This->mng, callback_closestream ); if(rv) err++;
- rv=mng_setcb_readdata (This->mng, callback_readdata ); if(rv) err++;
- rv=mng_setcb_processheader (This->mng, callback_processheader); if(rv) err++;
- rv=mng_setcb_getcanvasline (This->mng, callback_getcanvasline); if(rv) err++;
- rv=mng_setcb_refresh (This->mng, callback_refresh ); if(rv) err++;
- rv=mng_setcb_gettickcount (This->mng, callback_gettickcount ); if(rv) err++;
- rv=mng_setcb_settimer (This->mng, callback_settimer ); if(rv) err++;
- rv=mng_setcb_processtext (This->mng, callback_processtext ); if(rv) err++;
- #ifdef MNGPLG_TRACE
- rv=mng_setcb_traceproc (This->mng, callback_traceproc ); if(rv) err++;
- #endif
- if(err) {
- warn(This,"Error setting libmng callback functions");
- return 0;
- }
- rv= mng_set_suspensionmode (This->mng,MNG_TRUE);
- if(rv) {
- warn(This,"Error setting suspension mode");
- return 0;
- }
- // if the web page author provided a bgcolor, use it
- if(This->force_bgcolor) {
- rv=mng_set_bgcolor (This->mng, This->bg_r, This->bg_g, This->bg_b);
- }
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"initial readdisplay\n");
- #endif
- handle_read_error(This, mng_readdisplay(This->mng) );
- return 1;
- }
- /* Global initialization */
- static NPError NPP_Initialize(void)
- {
- if(!g_hInst) {
- warn(NULL,"MNG plugin error: Cannot load resources");
- }
- #ifdef MNGPLG_TRACE
- tracefile=fopen("c:\\temp\\mngtrace.txt","w");
- #endif
- #ifndef IDC_HAND
- #define IDC_HAND MAKEINTRESOURCE(32649)
- #endif
- hcurHandNS = LoadCursor(NULL,IDC_HAND);
- if(!hcurHandNS) {
- hcurHandNS=LoadCursor(g_hInst,"CURHAND_NS");
- }
- hfontMsg=CreateFont(-12,0,0,0,FW_DONTCARE,TRUE,0,0,ANSI_CHARSET,
- OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DRAFT_QUALITY,
- VARIABLE_PITCH|FF_SWISS,"Arial");
- return NPERR_NO_ERROR;
- }
- /* Global shutdown */
- static void NPP_Shutdown(void)
- {
- #ifdef MNGPLG_TRACE
- if(tracefile) {
- fclose(tracefile);
- tracefile=NULL;
- }
- #endif
- if(hfontMsg) DeleteObject((HGDIOBJ)hfontMsg);
- return;
- }
- static unsigned char gethex(const char *s)
- {
- int v[2];
- int i;
- v[0]=v[1]=0;
- for(i=0;i<2;i++) {
- if(s[i]>='a' && s[i]<='f') v[i]=s[i]-87;
- if(s[i]>='A' && s[i]<='F') v[i]=s[i]-55;
- if(s[i]>='0' && s[i]<='9') v[i]=s[i]-48;
- }
- return (unsigned char)(v[0]*16+v[1]);
- }
- static void hexcolor2rgb(const char *s, mng_uint16 *r, mng_uint16 *g, mng_uint16 *b)
- {
- if(lstrlen(s)!=7) return;
- if(s[0]!='#') return;
- (*r)= gethex(&s[1]); (*r)= ((*r)<<8)|(*r);
- (*g)= gethex(&s[3]); (*g)= ((*g)<<8)|(*g);
- (*b)= gethex(&s[5]); (*b)= ((*b)<<8)|(*b);
- }
- static void find_window_size(PluginInstance *This)
- {
- RECT r;
- if(This->scrolling) { // make sure scrollbars exist if needed
- ShowScrollBar(This->fhWnd,SB_BOTH,TRUE);
- }
- GetClientRect(This->fhWnd, &r);
- This->windowwidth=r.right;
- This->windowheight=r.bottom;
- }
- static void set_scrollbars(PluginInstance *This)
- {
- SCROLLINFO si;
- int maxpos;
- if(!This->scrolling) return;
- if(!This->fhWnd) return;
- ZeroMemory(&si,sizeof(SCROLLINFO));
- si.cbSize = sizeof(SCROLLINFO);
- // horizontal
- if(This->lpdib) {
- maxpos=This->lpdibinfo->biWidth-This->windowwidth;
- if(maxpos<0) maxpos=0;
- if(This->xscrollpos>maxpos) This->xscrollpos=maxpos;
- if(This->xscrollpos<0) This->xscrollpos=0;
-
- si.fMask = SIF_ALL|SIF_DISABLENOSCROLL;
- si.nMin = 0;
- si.nMax = This->lpdibinfo->biWidth -1;
- si.nPage = This->windowwidth;
- si.nPos = This->xscrollpos;
- }
- else { // no image to display
- si.fMask = SIF_ALL|SIF_DISABLENOSCROLL;
- si.nMin = 0;
- si.nMax = 0;
- si.nPage = 1;
- si.nPos = 0;
- }
- SetScrollInfo(This->fhWnd,SB_HORZ,&si,TRUE);
- // vertical
- if(This->lpdib) {
- maxpos=This->lpdibinfo->biHeight-This->windowheight;
- if(maxpos<0) maxpos=0;
- if(This->yscrollpos>maxpos) This->yscrollpos=maxpos;
- if(This->yscrollpos<0) This->yscrollpos=0;
- si.fMask = SIF_ALL|SIF_DISABLENOSCROLL;
- si.nMin = 0;
- si.nMax = This->lpdibinfo->biHeight -1;
- si.nPage = This->windowheight;
- si.nPos = This->yscrollpos;
- }
- SetScrollInfo(This->fhWnd,SB_VERT,&si,TRUE);
- }
- #define SCROLLLINE 40
- static void scrollmsg(PluginInstance *This, UINT msg,int code, short int pos)
- {
- int page;
- int dx, dy; // amount of scrolling
- int x_orig, y_orig;
- if(!This->scrolling) return;
- if(!This->lpdib) return;
- x_orig=This->xscrollpos;
- y_orig=This->yscrollpos;
- if(msg==WM_HSCROLL) {
- page=This->windowwidth-15;
- if(page<SCROLLLINE) page=SCROLLLINE;
- switch(code) {
- case SB_LINELEFT: This->xscrollpos-=SCROLLLINE; break;
- case SB_LINERIGHT: This->xscrollpos+=SCROLLLINE; break;
- case SB_PAGELEFT: This->xscrollpos-=page; break;
- case SB_PAGERIGHT: This->xscrollpos+=page; break;
- case SB_LEFT: This->xscrollpos=0; break;
- case SB_RIGHT: This->xscrollpos=This->lpdibinfo->biWidth; break;
- case SB_THUMBTRACK: This->xscrollpos=pos; break;
- default: return;
- }
- set_scrollbars(This);
- }
- else if(msg==WM_VSCROLL) {
- page=This->windowheight-15;
- if(page<SCROLLLINE) page=SCROLLLINE;
- switch(code) {
- case SB_LINEUP: This->yscrollpos-=SCROLLLINE; break;
- case SB_LINEDOWN: This->yscrollpos+=SCROLLLINE; break;
- case SB_PAGEUP: This->yscrollpos-=page; break;
- case SB_PAGEDOWN: This->yscrollpos+=page; break;
- case SB_TOP: This->yscrollpos=0; break;
- case SB_BOTTOM: This->yscrollpos=This->lpdibinfo->biHeight; break;
- case SB_THUMBTRACK: This->yscrollpos=pos; break;
- default: return;
- }
- set_scrollbars(This);
- }
- dx= x_orig - This->xscrollpos;
- dy= y_orig - This->yscrollpos;
- if(dx || dy) { // if any change
- // GetClientRect(This->fhWnd,&cliprect);
- ScrollWindowEx(This->fhWnd,dx,dy,NULL,NULL /*&cliprect*/,NULL,NULL,SW_INVALIDATE);
- }
- }
- /* Once-per-instance initialization */
- static NPError NPP_New(NPMIMEType pluginType,NPP instance,uint16 mode,
- int16 argc,char* argn[],char* argv[],NPSavedData* saved)
- {
- PluginInstance* This;
- int i;
-
- if (instance == NULL) {
- return NPERR_INVALID_INSTANCE_ERROR;
- }
- instance->pdata = calloc(sizeof(PluginInstance),1);
- This = (PluginInstance*) instance->pdata;
- if (This == NULL) {
- return NPERR_OUT_OF_MEMORY_ERROR;
- }
- This->force_bgcolor=1;
- This->bg_r = This->bg_g = This->bg_b = 0xffff;
- /* record some info for later lookup */
- This->fWindow = NULL;
- This->fMode = mode;
-
- This->fhWnd = NULL;
- This->fDefaultWindowProc = NULL;
- This->instance = instance; /* save the instance id for reverse lookups */
- This->scrolling = (mode==NP_FULL);
- This->xscrollpos = This->yscrollpos = 0;
- This->windowwidth = This->windowheight = 0;
- This->loadstate = STATE_INIT;
- This->paintedyet = 0;
- This->mng=0;
- This->lpdib=NULL;
- lstrcpy(This->url,"");
- This->frozen=0;
- This->needresume=0;
- This->errorflag=0;
- lstrcpy(This->errormsg,"");
- This->dibsize = This->filesize = 0;
- lstrcpy(This->linkurl,"");
- lstrcpy(This->linktarget,"_self");
- This->islink=0;
-
- This->timer_set=0;
- This->timer2_set=0;
- This->dynamicmng= -1;
- This->mouse_over_mng=0;
- This->mouse_captured=0;
- This->linkcursor = hcurHandNS;
- // examine the <embed> tag arguments
- for(i=0;i<argc;i++) {
- if(!_stricmp(argn[i],"bgcolor")) {
- This->force_bgcolor=1;
- hexcolor2rgb(argv[i],&This->bg_r,&This->bg_g,&This->bg_b);
- }
- else if(!_stricmp(argn[i],"href")) {
- lstrcpyn(This->linkurl,argv[i],MAXLEN_URL);
- This->islink=1;
- }
- else if(!_stricmp(argn[i],"target")) {
- lstrcpyn(This->linktarget,argv[i],MAXLEN_TARGET);
- }
- }
- This->bkgdbrush=NULL;
- if(This->force_bgcolor)
- This->bkgdbrush=CreateSolidBrush(RGB(This->bg_r,This->bg_g,This->bg_b));
- return NPERR_NO_ERROR;
- }
- static void BeforeDestroyWindow(PluginInstance *This)
- {
- if(This->timer_set) {
- KillTimer(This->fhWnd,1);
- This->timer_set=0;
- }
- if(This->timer2_set) {
- KillTimer(This->fhWnd,2);
- This->timer2_set=0;
- }
- if(This->mouse_captured) {
- ReleaseCapture();
- This->mouse_captured=0;
- }
- SetWindowLong( This->fhWnd, GWL_WNDPROC, (LONG)This->fDefaultWindowProc); // unsubclass
- This->fDefaultWindowProc = NULL;
- This->fhWnd = NULL;
- }
- static NPError NPP_Destroy(NPP instance, NPSavedData** save)
- {
- PluginInstance* This;
- if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR;
- This = (PluginInstance*) instance->pdata;
- if(!This) return NPERR_INVALID_INSTANCE_ERROR;
- if(This->mng) {
- This->dynamicmng=0;
- mng_cleanup(&This->mng);
- This->mng=0;
- }
- if(This->lpdib) {
- free(This->lpdib);
- This->lpdib=NULL;
- }
- if(This->mngdata) {
- free(This->mngdata);
- This->mngdata=NULL;
- This->bytesalloc=0;
- }
- if(This->textdata) {
- free(This->textdata);
- This->textdata=NULL;
- }
- if( This->fhWnd ) { // un-subclass the plugin window
- BeforeDestroyWindow(This);
- }
- if(This->bkgdbrush) DeleteObject((HGDIOBJ)This->bkgdbrush);
- if(This) {
- if(instance->pdata) free(instance->pdata);
- instance->pdata = NULL;
- }
- return NPERR_NO_ERROR;
- }
- /* Browser is providing us with a window */
- static NPError NPP_SetWindow(NPP instance, NPWindow* window)
- {
- NPError result = NPERR_NO_ERROR;
- PluginInstance* This;
- if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR;
- This = (PluginInstance*) instance->pdata;
- if( This->fhWnd != NULL ) { /* If we already have a window... */
- if( (window == NULL) || ( window->window == NULL ) ) {
- /* There is now no window to use. get rid of the old
- * one and exit. */
- BeforeDestroyWindow(This);
- This->fWindow=window;
- return NPERR_NO_ERROR;
- }
- else if ( This->fhWnd == (HWND) window->window ) {
- /* The new window is the same as the old one. Redraw and get out. */
- This->fWindow=window;
- InvalidateRect( This->fhWnd, NULL, FALSE );
- /* UpdateWindow( This->fhWnd ); */
- return NPERR_NO_ERROR;
- }
- else {
- /* Unsubclass the old window, so that we can subclass the new
- * one later. */
- BeforeDestroyWindow(This);
- }
- }
- else if( (window == NULL) || ( window->window == NULL ) ) {
- /* We can just get out of here if there is no current
- * window and there is no new window to use. */
- This->fWindow=window;
- return NPERR_NO_ERROR;
- }
- /* Subclass the new window so that we can begin drawing and
- * receiving window messages. */
- This->fDefaultWindowProc = (WNDPROC)SetWindowLong( (HWND)window->window, GWL_WNDPROC, (LONG)PluginWindowProc);
- This->fhWnd = (HWND) window->window;
- SetProp( This->fhWnd, gInstanceLookupString, (HANDLE)This);
- This->fWindow = window;
- find_window_size(This);
- set_scrollbars(This);
- InvalidateRect( This->fhWnd, NULL, TRUE );
- UpdateWindow( This->fhWnd );
- return result;
- }
- // browser is announcing its intent to send data to us
- static NPError NPP_NewStream(NPP instance,NPMIMEType type,NPStream *stream,
- NPBool seekable,uint16 *stype) {
- PluginInstance* This;
- if(instance==NULL)
- return NPERR_INVALID_INSTANCE_ERROR;
- This = (PluginInstance*) instance->pdata;
- if(!This)
- return NPERR_GENERIC_ERROR;
- /* save the URL for later */
- lstrcpyn(This->url,stream->url,MAX_PATH);
- This->libmngpos=0;
- This->bytesloaded=0;
- This->bytesalloc=0;
- This->byteswanted=0;
- This->mngdata=NULL;
- This->textdata=NULL;
- // if we know the total length of the stream in advance
- // (most of the time we will, hopefully), allocate that amount.
- if(stream->end > 0) {
- This->mngdata = malloc(stream->end);
- This->bytesalloc= stream->end;
- }
- my_init_mng(This);
- This->loadstate=STATE_LOADING;
- (*stype)=NP_NORMAL;
- return NPERR_NO_ERROR;
- }
- static int32 NPP_WriteReady(NPP instance, NPStream *stream)
- {
- /* Number of bytes ready to accept in NPP_Write() */
- /* We can handle any amount, so just return some really big number. */
- return (int32)0X0FFFFFFF;
- }
- #define ALLOC_CHUNK_SIZE 131072
- static int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
- {
- PluginInstance* This;
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"NPP_Write offs=%d len=%d\n",offset,len);
- #endif
- if(!instance) return -1;
- This = (PluginInstance*) instance->pdata;
- if(!This) return -1;
- if(len<1) return len;
- if(offset+len > (int)This->bytesalloc) { // oops, overflowed our memory buffer
- This->bytesalloc += ALLOC_CHUNK_SIZE;
- if(This->mngdata) {
- This->mngdata=realloc(This->mngdata, This->bytesalloc);
- }
- else { // first time
- This->mngdata=malloc(This->bytesalloc);
- }
- if(!This->mngdata) {
- warn(This,"Cannot allocate memory for image (%d,%d,%p",offset,len,buffer);
- return -1;
- }
- }
- // now we should have enough room to copy the data to memory
- CopyMemory(&This->mngdata[offset],buffer,len);
- This->bytesloaded = offset+len;
- // now, check if it's time to call mng_read_resume
- if(This->needresume &&
- (This->bytesloaded >= (This->libmngpos + This->byteswanted)) )
- {
- This->needresume=0;
- // handle_read_error(This, mng_read_resume(This->mng) );
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"NPP_Write display_resume bytesloaded=%d libmngpos=%d byteswanted=%d\n",
- This->bytesloaded,This->libmngpos,This->byteswanted);
- #endif
- handle_read_error(This, mng_display_resume(This->mng) );
- }
- return len; // The number of bytes accepted -- we always accept them all.
- }
- /* DestroyStream gets called after the file has finished loading,
- */
- static NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
- {
- PluginInstance* This;
- if(!instance) return NPERR_INVALID_INSTANCE_ERROR;
- This = (PluginInstance*) instance->pdata;
- // if(reason==NPRES_DONE) {
- This->filesize = This->bytesloaded;
- This->loadstate = STATE_LOADED;
- // }
- if(reason!=NPRES_DONE) {
- set_error(This,"Image load failed or was canceled (%d)",(int)reason);
- This->needresume=0;
- if(This->timer_set) { KillTimer(This->fhWnd,1); This->timer_set=0; }
- return NPERR_NO_ERROR;
- }
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"NPP_DestroyStream reason=%d needresume=%d\n",reason,This->needresume);
- #endif
- if(This->needresume) {
- This->needresume=0;
- // handle_read_error(This, mng_read_resume(This->mng) );
- handle_read_error(This, mng_display_resume(This->mng) );
- // This->needresume=0;
- }
- return NPERR_NO_ERROR;
- }
- static void NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
- {
- return;
- }
- // Print embedded plug-in (via the browser's Print command)
- static void NPP_Print(NPP instance, NPPrint* printInfo)
- {
- PluginInstance* This;
- if (instance == NULL) return;
- This = (PluginInstance*) instance->pdata;
- if(printInfo == NULL) {
- // Some browsers (Netscape) set printInfo to NULL to tell the plugin
- // to print in full page mode (this may be a bug).
- // PrintFullPage(); -- full page printing not implemented
- return;
- }
-
- if (printInfo->mode == NP_FULL) {
- /* the plugin is full-page, and the browser is giving it a chance
- * to print in the manner of its choosing */
- void* platformPrint = printInfo->print.fullPrint.platformPrint;
- NPBool printOne = printInfo->print.fullPrint.printOne;
-
- /* Setting this to FALSE and returning *should* cause the browser to
- * call NPP_Print again, this time with mode=NP_EMBED.
- * However, that doesn't happen with any browser I've ever seen :-(.
- * Instead of the following line, you will probably need to implement
- * printing yourself. You also might as well set pluginPrinted to TRUE,
- * though every browser I've tested ignores it. */
- printInfo->print.fullPrint.pluginPrinted = FALSE;
- /* or */
- /* PrintFullPage();
- * printInfo->print.fullPrint.pluginPrinted = TRUE; */
- }
- else { // we are embedded, and the browser had provided a printer context
- HDC pdc;
- int prevstretchmode;
- NPWindow* printWindow;
-
- if(This->loadstate < STATE_VALIDFRAME) return;
- printWindow= &(printInfo->print.embedPrint.window);
- /* embedPrint.platformPrint is a Windows device context in disguise */
- /* The definition of NPWindow changed between API verion 0.9 and 0.11,
- * increasing in size from 28 to 32 bytes. This normally makes it
- * impossible for version 0.9 browsers to print version 0.11 plugins
- * (because the platformPrint field ends up at the wrong offset) --
- * unless the plugin takes special care to detect this situation.
- * To work around it, if we are compiled with API 0.11 or higher,
- * and the browser is version 0.9 or earlier, we look for the HDC
- * 4 bytes earlier, at offset 28 instead of 32 (of the embedPrint
- * sub-structure).
- */
- if(sizeof(NPWindow)>28 && /* i.e. is plugin API >= 0.11? */
- HIBYTE(g_pNavigatorFuncs->version)==0 &&
- LOBYTE(g_pNavigatorFuncs->version)<=9) {
- char *tmpc;
- HDC *tmph;
- tmpc= (char*)&(printInfo->print.embedPrint);
- tmph= (HDC*)&tmpc[28];
- pdc= *tmph;
- }
- else {
- pdc= (HDC) (printInfo->print.embedPrint.platformPrint);
- }
- if(!This->lpdib) return;
- prevstretchmode=SetStretchBltMode(pdc,COLORONCOLOR);
- StretchDIBits(pdc,
- printWindow->x,printWindow->y,
- printWindow->width,printWindow->height, /* dest coords */
- 0,0,This->lpdibinfo->biWidth, This->lpdibinfo->biHeight, /* source coords */
- This->lpdibbits, (LPBITMAPINFO)This->lpdib,
- DIB_RGB_COLORS,SRCCOPY);
- if(prevstretchmode) SetStretchBltMode(pdc,prevstretchmode);
- }
- return;
- }
- /*+++++++++++++++++++++++++++++++++++++++++++++++++
- * NPP_URLNotify:
- * Notifies the instance of the completion of a URL request.
- +++++++++++++++++++++++++++++++++++++++++++++++++*/
- static void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
- {
- return;
- }
- /**********************************************************************/
- /* Try to make a filename from the url. Caller must provide fn[MAX_PATH] buffer.
- * This function attempts to extract a bitmap filename from a URL,
- * but if it doesn't look like it contains an appropriate name,
- * it leaves it blank. */
- static void url2filename(char *fn, char *url)
- {
- int title,ext,i;
- lstrcpy(fn,"");
- ext=0; /* position of the file extention */
- title=0; /* position of the base filename */
- for(i=0;url[i];i++) {
- if(url[i]=='.') ext=i+1;
- if(url[i]=='/') title=i+1;
- if(url[i]=='\\') title=i+1; // handle Microsoft's bogus file: "URLs"
- if(url[i]==':') title=i+1;
- if(url[i]=='=') title=i+1;
- }
- if (!_stricmp(&url[ext],"mng") ||
- !_stricmp(&url[ext],"jng") ||
- !_stricmp(&url[ext],"png") )
- {
- lstrcpyn(fn,&url[title],MAX_PATH);
- }
- }
- // sanitize string and escape '&'s for use in a menu
- static void escapeformenu(unsigned char *s1)
- {
- int f, t, len;
- unsigned char s2[200];
- t=0;
- len=lstrlen(s1); if(len>50) len=50;
- for(f=0;f<len;f++) {
- if(s1[f]=='&') {
- s2[t++]='&';
- s2[t++]='&';
- }
- else if(s1[f]<32) {
- s2[t++]='_';
- }
- else {
- s2[t++]=s1[f];
- }
- }
- s2[t]='\0';
- lstrcpy(s1,s2);
- }
- static char *get_imagetype_name(mng_imgtype t)
- {
- switch(t) {
- case mng_it_mng: return "MNG";
- case mng_it_png: return "PNG";
- case mng_it_jng: return "JNG";
- }
- return "Unknown";
- }
- /* Write the image to a local file */
- static void SaveImage(PluginInstance *This)
- {
- OPENFILENAME ofn;
- char fn[MAX_PATH];
- HANDLE hfile;
- BOOL b;
- mng_imgtype t;
- DWORD byteswritten;
- if(!This->mng || This->loadstate<STATE_LOADED ||
- This->bytesloaded != This->filesize)
- {
- warn(This,"Image not loaded -- can't save");
- return;
- }
- if(lstrlen(This->url)) {
- url2filename(fn,This->url);
- }
- else {
- lstrcpy(fn,"");
- }
- ZeroMemory(&ofn,sizeof(OPENFILENAME));
- ofn.lStructSize=sizeof(OPENFILENAME);
- ofn.hwndOwner=This->fhWnd;
- ofn.nFilterIndex=1;
- ofn.lpstrTitle="Save Image As...";
- ofn.lpstrFile=fn;
- ofn.nMaxFile=MAX_PATH;
- ofn.Flags=OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
- t=mng_get_sigtype(This->mng);
- if(t==mng_it_png) {
- ofn.lpstrDefExt="png"; // FIXME also give an option of MNG
- ofn.lpstrFilter="PNG (*.png)\0*.png\0\0";
- }
- else if(t==mng_it_jng) {
- ofn.lpstrDefExt="jng"; // FIXME also give an option of MNG
- ofn.lpstrFilter="JNG (*.jng)\0*.jng\0\0";
- }
- else {
- ofn.lpstrFilter="MNG (*.mng)\0*.mng\0\0";
- ofn.lpstrDefExt="mng";
- }
- if(GetSaveFileName(&ofn)) {
- // save to filename: ofn.lpstrFile
- hfile=CreateFile(ofn.lpstrFile,GENERIC_WRITE,FILE_SHARE_READ,
- NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- if(hfile==INVALID_HANDLE_VALUE) {
- warn(This,"Unable to write file");
- }
- else {
- b=WriteFile(hfile, This->mngdata, This->filesize,
- &byteswritten,NULL);
- if(!b || byteswritten != This->filesize) {
- warn(This,"Error writing file");
- }
- CloseHandle(hfile);
- }
- }
- }
- static void CopyToClipboard(PluginInstance *This,unsigned char *mem,int size,UINT format)
- {
- HGLOBAL hClip;
- LPVOID lpClip;
- if(!mem) return;
- if(!OpenClipboard(NULL)) {
- warn(This,"Can't open the clipboard");
- return;
- }
- if(EmptyClipboard()) {
- hClip=GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,size);
- lpClip=GlobalLock(hClip);
- if(lpClip) {
- CopyMemory(lpClip,mem,size);
- GlobalUnlock(hClip);
- if(!SetClipboardData(format,hClip)) {
- warn(This,"Can't set clipboard data");
- }
- }
- else {
- warn(This,"Can't allocate memory for clipboard");
- }
- }
- else {
- warn(This,"Can't clear the clipboard");
- }
- CloseClipboard();
- }
- static void AboutDialog(PluginInstance *This)
- {
- DialogBoxParam(g_hInst,"ABOUTDLG",This->fhWnd,(DLGPROC)DlgProcAbout,(LPARAM)This);
- }
- static void PropDialog(PluginInstance *This)
- {
- //if(This->textdata)
- DialogBoxParam(g_hInst,"PROPDLG",This->fhWnd,(DLGPROC)DlgProcProp,(LPARAM)This);
- }
- static void display_last_error(PluginInstance *This)
- {
- if(This->errorflag) {
- warn(This,"%s",This->errormsg);
- }
- }
- static void DynamicMNG_FireEvent(PluginInstance *This, mng_uint8 eventtype, POINTS pos)
- {
- mng_retcode r;
- if(!This->mng) return;
- if(This->dynamicmng == 0) return;
- if(This->dynamicmng == -1) {
- r=mng_status_dynamic(This->mng);
- if(r==MNG_FALSE) {
- return;
- }
- else {
- This->dynamicmng=1;
- }
- }
- mng_trapevent(This->mng, eventtype, pos.x+This->xscrollpos, pos.y+This->yscrollpos);
- }
- static void ContextMenu(PluginInstance *This, HWND hwnd)
- {
- int cmd;
- HMENU menu;
- POINT pt;
- unsigned char buf[MAX_PATH], buf2[200];
- pt.x=0; pt.y=0;
- GetCursorPos(&pt);
- // create context menu dynamically
- menu=CreatePopupMenu();
- if(This->errorflag) {
- AppendMenu(menu,MF_ENABLED,ID_SHOWERROR,"SHOW ERROR MESSAGE");
- AppendMenu(menu,MF_SEPARATOR,0,NULL);
- }
- AppendMenu(menu,(This->loadstate>=STATE_LOADED?MF_ENABLED:MF_GRAYED),ID_SAVEAS,"Save Image &As...");
- AppendMenu(menu,(This->lpdib?MF_ENABLED:MF_GRAYED),ID_COPYIMAGE,"&Copy Image");
- AppendMenu(menu,MF_ENABLED,ID_COPYURL,"Cop&y Image Location");
- if(This->islink) {
- AppendMenu(menu,MF_ENABLED,ID_COPYLINKLOC,"Copy Link Location");
- }
- url2filename(buf,This->url);
- escapeformenu(buf);
- if(lstrlen(buf)) {
- wsprintf(buf2,"View Image (%s)",buf);
- }
- else {
- wsprintf(buf2,"View Image");
- }
- AppendMenu(menu,MF_ENABLED,ID_VIEWIMAGE,buf2);
- AppendMenu(menu,MF_SEPARATOR,0,NULL);
- // AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED),ID_STOPANIM,"Stop Animation");
- AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED)|
- (This->frozen?MF_CHECKED:MF_UNCHECKED),ID_FREEZE,"&Freeze Animation");
- // AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED),ID_RESTARTANIM,"Restart Animation");
- AppendMenu(menu,MF_SEPARATOR,0,NULL);
- AppendMenu(menu,MF_ENABLED,ID_PROPERTIES,"Properties...");
- AppendMenu(menu,MF_ENABLED,ID_ABOUT,"About MNG Plug-in...");
- cmd=TrackPopupMenuEx(menu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_NONOTIFY|TPM_RETURNCMD|
- TPM_RIGHTBUTTON,pt.x,pt.y,hwnd,NULL);
- DestroyMenu(menu);
- switch(cmd) {
- case ID_STOPANIM:
- if(This->mng) {
- KillTimer(This->fhWnd,1);
- This->timer_set=0;
- mng_display_freeze(This->mng);
- }
- break;
- case ID_FREEZE:
- This->frozen = !This->frozen;
- if(This->frozen) {
- KillTimer(This->fhWnd,1);
- This->timer_set=0;
- mng_display_freeze(This->mng);
- }
- else {
- handle_read_error(This, mng_display_resume(This->mng) );
- }
- break;
- case ID_RESTARTANIM:
- if(!This->frozen) {
- KillTimer(This->fhWnd,1);
- This->timer_set=0;
- mng_display_freeze(This->mng);
- }
- This->frozen=1;
- mng_display_reset(This->mng);
- This->frozen=0;
- handle_read_error(This, mng_display_resume(This->mng) );
- break;
- case ID_SAVEAS:
- SaveImage(This);
- break;
- case ID_COPYIMAGE:
- if(This->lpdib) {
- CopyToClipboard(This,(unsigned char*)This->lpdib,This->dibsize,CF_DIB);
- }
- else {
- warn(This,"No image to copy");
- }
- break;
- case ID_COPYURL:
- CopyToClipboard(This,This->url,lstrlen(This->url)+1,CF_TEXT);
- break;
- case ID_COPYLINKLOC:
- if(This->islink) {
- CopyToClipboard(This,This->linkurl,lstrlen(This->linkurl)+1,CF_TEXT);
- }
- break;
- case ID_VIEWIMAGE:
- if(lstrlen(This->url))
- NPN_GetURL(This->instance,This->url,"_self");
- break;
- case ID_PROPERTIES:
- PropDialog(This);
- break;
- case ID_ABOUT:
- AboutDialog(This);
- break;
- case ID_SHOWERROR:
- display_last_error(This);
- break;
- }
- }
- /*+++++++++++++++++++++++++++++++++++++++++++++++++
- * PluginWindowProc
- * Handle the Windows window-event loop.
- +++++++++++++++++++++++++++++++++++++++++++++++++*/
- static LRESULT CALLBACK PluginWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
- {
- PluginInstance* This;
- HDC hdc;
- RECT rect;
-
- This = (PluginInstance*) GetProp(hWnd, gInstanceLookupString);
- if(!This) return DefWindowProc( hWnd, Msg, wParam, lParam);
- switch(Msg) {
- case WM_ERASEBKGND:
- {
- HBRUSH br;
- hdc= (HDC)wParam;
- if(This->bkgdbrush)
- br=This->bkgdbrush;
- else
- br=GetStockObject(GRAY_BRUSH);
- GetClientRect(hWnd,&rect);
- FillRect(hdc,&rect,br);
- return 1;
- }
- case WM_HSCROLL:
- case WM_VSCROLL:
- scrollmsg(This,Msg,(int)(LOWORD(wParam)),(short int)(HIWORD(wParam)));
- return 0;
- case WM_SIZE:
- find_window_size(This);
- set_scrollbars(This);
- return 0;
- case WM_CONTEXTMENU: case WM_RBUTTONUP:
- ContextMenu(This, hWnd);
- return 0;
- case WM_SETCURSOR:
- if(LOWORD(lParam)==HTCLIENT) {
- if(This->islink) {
- SetCursor(This->linkcursor);
- return 1;
- }
- }
- break;
- case WM_LBUTTONDOWN:
- SetCapture(This->fhWnd);
- This->mouse_captured=1;
- if(This->dynamicmng && This->mng && !This->errorflag) {
- DynamicMNG_FireEvent(This,4,MAKEPOINTS(lParam));
- }
- return 0;
-
- case WM_LBUTTONUP:
- {
- RECT rc;
- POINT pt;
- if(This->mouse_captured) {
- ReleaseCapture();
- This->mouse_captured=0;
- }
- if(This->dynamicmng && This->mng && !This->errorflag) {
- DynamicMNG_FireEvent(This,5,MAKEPOINTS(lParam));
- }
- // if mouse is not over image, don't follow links, etc.
- GetWindowRect(This->fhWnd,&rc);
- GetCursorPos(&pt);
- if(!PtInRect(&rc,pt)) return 0;
- if(This->islink) {
- NPN_GetURL(This->instance,This->linkurl,This->linktarget);
- return 0;
- }
- else if(This->errorflag) {
- display_last_error(This);
- }
- }
- return 0;
- case WM_MOUSEMOVE:
- if(This->dynamicmng && This->mng && This->lpdib && !This->errorflag) {
- POINTS pos;
- int overimage;
- pos=MAKEPOINTS(lParam);
- overimage=0;
- if(pos.x>=0 && pos.x<This->lpdibinfo->biWidth && pos.y>=0 && pos.y<This->lpdibinfo->biHeight) {
- overimage=1;
- }
- if(overimage) {
- if(This->mouse_over_mng) {
- // mouse is still over image: mouse move event
- DynamicMNG_FireEvent(This,2,pos); // 2=mouse move
- }
- else {
- // mouse wasn't over the image but now it is: mouse-enter event
- DynamicMNG_FireEvent(This,1,pos); // mouse enter
- }
- }
- else { // mouse not now over image
- if(This->mouse_over_mng) { // ... but it used to be
- pos.x=0; pos.y=0;
- DynamicMNG_FireEvent(This,3,pos); // 3=mouse leave
- }
- }
- This->mouse_over_mng=overimage; // remember for next time
- if(This->mouse_over_mng && (This->dynamicmng==1) ) {
- #define MOUSE_POLL_INTERVAL 100 // milliseconds
- SetTimer(This->fhWnd,2,MOUSE_POLL_INTERVAL,NULL);
- This->timer2_set=0;
- }
- }
- return 0;
- case WM_PAINT:
- {
- PAINTSTRUCT paintStruct;
- HDC hdc;
- RECT rect2;
- hdc = BeginPaint( hWnd, &paintStruct );
- SetWindowOrgEx(hdc,This->xscrollpos,This->yscrollpos,NULL);
- GetClientRect(hWnd,&rect);
- if(This) {
- if(This->errorflag || !This->lpdib) {
- SelectObject(hdc,hfontMsg);
- Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);
- rect2.left=rect.left+2;
- rect2.top=rect.top+2;
- rect2.right=rect.right-2;
- rect2.bottom=rect.bottom-2;
- if(This->errorflag) {
- DrawText(hdc,"MNG PLUG-IN ERROR!",-1,&rect2,DT_LEFT|DT_WORDBREAK);
- }
- else {
- if(This->loadstate>=STATE_LOADING) {
- DrawText(hdc,"MNG image loading...",-1,&rect2,DT_LEFT|DT_WORDBREAK);
- }
- else {
- DrawText(hdc,"MNG plug-in",-1,&rect2,DT_LEFT|DT_WORDBREAK);
- }
- }
- }
- else if(This->lpdib) {
- StretchDIBits(hdc,
- 0,0,This->lpdibinfo->biWidth,This->lpdibinfo->biHeight,
- 0,0,This->lpdibinfo->biWidth,This->lpdibinfo->biHeight,
- &((BYTE*)(This->lpdib))[sizeof(BITMAPINFOHEADER)],
- (LPBITMAPINFO)This->lpdib,DIB_RGB_COLORS,SRCCOPY);
- }
- }
- EndPaint( hWnd, &paintStruct );
- }
- return 0;
- case WM_TIMER:
- switch(wParam) {
- case 1: // the main animation timer
- KillTimer(hWnd,1);
- This->timer_set=0;
- #ifdef MNGPLG_TRACE
- fprintf(tracefile,"WM_TIMER display_resume bytesloaded=%d\n",This->bytesloaded);
- #endif
- if(This->mng) {
- if(!This->needresume) {
- handle_read_error(This, mng_display_resume(This->mng) );
- }
- }
- return 0;
- case 2: // timer for polling mouse position
- {
- RECT rc;
- POINT pt;
- POINTS pos;
- GetWindowRect(hWnd,&rc);
- GetCursorPos(&pt);
- if(!PtInRect(&rc,pt)) {
- KillTimer(hWnd,2);
- pos.x=0; pos.y=0;
- DynamicMNG_FireEvent(This,3,pos); // 3=mouse leave
- This->mouse_over_mng=0;
- }
- }
- return 0;
- }
- break;
- }
- /* Forward unprocessed messages on to their original destination
- * (the window proc we replaced) */
- return This->fDefaultWindowProc(hWnd, Msg, wParam, lParam);
- }
- static LRESULT CALLBACK DlgProcProp(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
- {
- char buf[4096],buf2[1024];
- switch(Msg) {
- case WM_INITDIALOG:
- {
- DWORD tabs[1];
- PluginInstance *This=(PluginInstance*)lParam;
- tabs[0]= 60;
- SendDlgItemMessage(hWnd,IDC_IMGINFO,EM_SETTABSTOPS,(WPARAM)1,(LPARAM)tabs);
- wsprintf(buf,"URL:\t%s\r\n",This->url);
- if(This->lpdib) {
- wsprintf(buf2,"Dimensions:\t%d x %d\r\n",This->lpdibinfo->biWidth,
- This->lpdibinfo->biHeight);
- lstrcat(buf,buf2);
- }
- if(This->lpdib && This->fMode==NP_EMBED) {
- wsprintf(buf2,"Window:\t%d x %d\r\n",This->windowwidth,
- This->windowheight);
- lstrcat(buf,buf2);
- }
- if(This->filesize) {
- wsprintf(buf2,"File size:\t%u bytes\r\n",This->filesize);
- lstrcat(buf,buf2);
- }
- #ifdef _DEBUG
- if(This->mngdata && This->lpdib && This->bytesalloc && This->dibsize) {
- // note this doesn't include memory used by libmng
- wsprintf(buf2,"Memory used:\t%u bytes\r\n",
- This->bytesalloc + This->dibsize);
- lstrcat(buf,buf2);
- }
- #endif
- if(This->islink) {
- wsprintf(buf2,"Link to:\t%s\r\n",This->linkurl);
- lstrcat(buf,buf2);
- if(strcmp(This->linktarget,"_self")) {
- wsprintf(buf2,"Link target:\t%s\r\n",This->linktarget);
- lstrcat(buf,buf2);
- }
- }
- if(This->loadstate >= STATE_VALIDFRAME) {
- wsprintf(buf2,"Signature:\t%s\r\n",get_imagetype_name(mng_get_sigtype(This->mng)));
- lstrcat(buf,buf2);
- wsprintf(buf2,"Image type:\t%s\r\n",get_imagetype_name(mng_get_imagetype(This->mng)));
- lstrcat(buf,buf2);
- wsprintf(buf2,"Simplicity:\t0x%08x\r\n",mng_get_simplicity(This->mng));
- lstrcat(buf,buf2);
- wsprintf(buf2,"Frame count:\t%u\r\n",mng_get_framecount(This->mng));
- lstrcat(buf,buf2);
- wsprintf(buf2,"Layer count:\t%u\r\n",mng_get_layercount(This->mng));
- lstrcat(buf,buf2);
- wsprintf(buf2,"Play time:\t%u\r\n",mng_get_playtime(This->mng));
- lstrcat(buf,buf2);
- }
- SetDlgItemText(hWnd,IDC_IMGINFO,buf);
- if(This->textdata)
- SetDlgItemText(hWnd,IDC_MNGTEXT,This->textdata);
- }
- return(TRUE);
- case WM_CLOSE:
- EndDialog(hWnd,0);
- return(TRUE);
- case WM_COMMAND:
- switch(wParam) {
- case IDOK:
- case IDCANCEL:
- EndDialog(hWnd,0);
- return(TRUE);
- }
- }
- return(FALSE);
- }
- static LRESULT CALLBACK DlgProcAbout(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
- {
- char buf[4096],buf2[1024],buf3[300];
- switch(Msg) {
- case WM_INITDIALOG:
- {
- //DWORD tabs[1];
- PluginInstance *This=(PluginInstance*)lParam;
- //tabs[0]= 60;
- //SendDlgItemMessage(hWnd,IDC_IMGINFO,EM_SETTABSTOPS,(WPARAM)1,(LPARAM)tabs);
- wsprintf(buf,"MNGPLG Plug-in, Version %s\r\n%s"
- #ifdef _DEBUG
- " DEBUG BUILD"
- #endif
- "\r\nCopyright (C) 2000-2002 by Jason Summers\r\n\r\n",MNGPLGVERS,__DATE__);
- wsprintf(buf2,"Based on libmng by Gerard Juyn.\r\n");
- lstrcat(buf,buf2);
- wsprintf(buf2,"libmng version: %s\r\n\r\n",mng_version_text());
- lstrcat(buf,buf2);
- wsprintf(buf2,"Uses the zlib compression library.\r\n");
- lstrcat(buf,buf2);
- wsprintf(buf2,"zlib version: %s\r\n\r\n",zlibVersion());
- lstrcat(buf,buf2);
- wsprintf(buf2,"This software is based in part on the work of the "
- "Independent JPEG Group.\r\n");
- lstrcat(buf,buf2);
- // This really only gives the version of the libjpeg header used when
- // compiling this plugin, but I don't know how to query libjpeg for its
- // version.
- wsprintf(buf2,"IJG JPEG library version: %s\r\n%s\r\n\r\n",JVERSION,JCOPYRIGHT);
- lstrcat(buf,buf2);
- #ifdef MNGPLG_CMS
- wsprintf(buf2,"Uses the lcms color management library by Martí Maria. "
- "lcms is distributed under the terms of the GNU LESSER GENERAL PUBLIC LICENSE. "
- "See the file COPYING-LCMS.\r\n\r\n");
- lstrcat(buf,buf2);
- #endif
- if(GetModuleFileName(g_hInst,buf3,260)) {
- wsprintf(buf2,"MNGPLG location: %s\r\n",buf3);
- lstrcat(buf,buf2);
- }
- SetDlgItemText(hWnd,IDC_PRGINFO,buf);
- }
- return(TRUE);
- case WM_CLOSE:
- EndDialog(hWnd,0);
- return(TRUE);
- case WM_COMMAND:
- switch(wParam) {
- case IDOK:
- case IDCANCEL:
- EndDialog(hWnd,0);
- return(TRUE);
- }
- }
- return(FALSE);
- }
- /////////////////////
- ///////////////////// low-level plug-in NPAPI functions
- static JRIGlobalRef Private_GetJavaClass(void)
- {
- return NULL;
- }
- NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pFuncs)
- {
- if(!pFuncs) return NPERR_INVALID_FUNCTABLE_ERROR;
- pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
- pFuncs->newp = NPP_New;
- pFuncs->destroy = NPP_Destroy;
- pFuncs->setwindow = NPP_SetWindow;
- pFuncs->newstream = NPP_NewStream;
- pFuncs->destroystream = NPP_DestroyStream;
- pFuncs->asfile = NPP_StreamAsFile;
- pFuncs->writeready = NPP_WriteReady;
- pFuncs->write = NPP_Write;
- pFuncs->print = NPP_Print;
- pFuncs->event = NULL;
- g_pluginFuncs = pFuncs;
- return NPERR_NO_ERROR;
- }
- NPError WINAPI NP_Initialize(NPNetscapeFuncs* pFuncs)
- {
- int navMinorVers;
- if(!pFuncs) return NPERR_INVALID_FUNCTABLE_ERROR;
- g_pNavigatorFuncs = pFuncs; // save it for future reference
- if(HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
- return NPERR_INCOMPATIBLE_VERSION_ERROR;
- navMinorVers = g_pNavigatorFuncs->version & 0xFF;
- if(navMinorVers>=NPVERS_HAS_NOTIFICATION)
- g_pluginFuncs->urlnotify = NPP_URLNotify;
- if( navMinorVers>=NPVERS_HAS_LIVECONNECT)
- g_pluginFuncs->javaClass = Private_GetJavaClass();
- return NPP_Initialize();
- }
- NPError WINAPI NP_Shutdown()
- {
- NPP_Shutdown();
- g_pNavigatorFuncs = NULL;
- return NPERR_NO_ERROR;
- }
|