npmngplg.c 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936
  1. /* -*- Mode: C; tab-width: 4; -*- */
  2. /* npmngplg.c
  3. * MNG browser plugin
  4. * By Jason Summers
  5. * Based on libmng by Gerard Juyn
  6. */
  7. #include <windows.h>
  8. #include <commdlg.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <malloc.h>
  13. #include <stdarg.h>
  14. #include "resource.h"
  15. #include "libmng.h"
  16. #include "jversion.h" // part of libjpeg
  17. #include "zlib.h" // for zlibVersion
  18. #include "npapidefs.h"
  19. #define MNGPLG_CMS
  20. //#define MNGPLG_TRACE
  21. #define IDBASE 47000
  22. #define ID_SAVEAS (IDBASE+0)
  23. #define ID_COPYIMAGE (IDBASE+1)
  24. #define ID_COPYURL (IDBASE+2)
  25. #define ID_VIEWIMAGE (IDBASE+3)
  26. #define ID_ABOUT (IDBASE+4)
  27. #define ID_FREEZE (IDBASE+5)
  28. #define ID_RESTARTANIM (IDBASE+6)
  29. #define ID_COPYLINKLOC (IDBASE+7)
  30. #define ID_STOPANIM (IDBASE+8)
  31. #define ID_SHOWERROR (IDBASE+9)
  32. #define ID_PROPERTIES (IDBASE+10)
  33. #define MNGPLGVERS "1.0.1"
  34. /* instance-specific data */
  35. typedef struct pluginstruct_
  36. {
  37. NPWindow* fWindow;
  38. uint16 fMode;
  39. HWND fhWnd;
  40. WNDPROC fDefaultWindowProc;
  41. NPP instance;
  42. mng_handle mng;
  43. #define STATE_INIT 0
  44. #define STATE_LOADING 1 // stream opened
  45. #define STATE_VALIDFRAME 2 // at least one frame has been displayed
  46. #define STATE_LOADED 3 // image loaded; stream closed
  47. #define MAXLEN_TEXT 5000
  48. #define MAXLEN_URL 300
  49. #define MAXLEN_TARGET 100
  50. // I think I'm not doing this very well. Probably there really needs to be
  51. // two state variables, one for loading from the network, and one for
  52. // the libmng processing. (or use libmng's new getstate API?)
  53. int loadstate;
  54. int paintedyet;
  55. int scrolling; // allow scrolling of the image?
  56. int xscrollpos, yscrollpos;
  57. int windowwidth, windowheight; // client size of current window
  58. int diblinesize;
  59. DWORD dibsize;
  60. DWORD filesize;
  61. DWORD libmngpos; // count of bytes that have been sent to libmng
  62. DWORD byteswanted; // libmng asked for this many more bytes (add to libmngpos)
  63. unsigned char *mngdata; // stores the MNG file in memory
  64. DWORD bytesloaded; //
  65. DWORD bytesalloc; // size of mngdata
  66. int needresume; // if previous mng_readdisplay call returned NEEDMOREDATA
  67. char *textdata;
  68. int errorflag; // set if an error occurs that prevents displaying the image
  69. char errormsg[256];
  70. unsigned char *lpdib; // pointer to header section of dib
  71. unsigned char *lpdibbits; // pointer to "bits" section of dib (follows the header)
  72. LPBITMAPINFOHEADER lpdibinfo; // alias for lpdib
  73. int frozen;
  74. int timer_set;
  75. int timer2_set;
  76. int dynamicmng;
  77. int mouse_over_mng;
  78. int mouse_captured;
  79. int force_bgcolor;
  80. mng_uint16 bg_r,bg_g,bg_b; // background color
  81. unsigned char url[MAX_PATH]; // the url of the stream
  82. int islink;
  83. HCURSOR linkcursor;
  84. HBRUSH bkgdbrush;
  85. unsigned char linkurl[MAXLEN_URL];
  86. unsigned char linktarget[MAXLEN_TARGET];
  87. } PluginInstance;
  88. /* global variables */
  89. #ifdef MNGPLG_TRACE
  90. static FILE *tracefile;
  91. #endif
  92. static const char* gInstanceLookupString = "pdata";
  93. static HMODULE g_hInst = NULL;
  94. static HCURSOR hcurHandNS;
  95. static HFONT hfontMsg;
  96. /* function prototypes */
  97. LRESULT CALLBACK DlgProcAbout(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
  98. LRESULT CALLBACK DlgProcProp(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
  99. LRESULT CALLBACK PluginWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
  100. void set_scrollbars(PluginInstance *This);
  101. //////////////////////////// NPN_functions
  102. static NPNetscapeFuncs* g_pNavigatorFuncs;
  103. static NPPluginFuncs* g_pluginFuncs;
  104. static const char* NPN_UserAgent(NPP instance)
  105. {
  106. return g_pNavigatorFuncs->uagent(instance);
  107. }
  108. static NPError NPN_GetURL(NPP instance, const char *url, const char *target)
  109. {
  110. return g_pNavigatorFuncs->geturl(instance, url, target);
  111. }
  112. /* ----------------------------------------------------------------------- */
  113. BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved)
  114. {
  115. switch(reason) {
  116. case DLL_PROCESS_ATTACH:
  117. g_hInst=hModule;
  118. break;
  119. case DLL_THREAD_ATTACH:
  120. break;
  121. case DLL_THREAD_DETACH:
  122. break;
  123. case DLL_PROCESS_DETACH:
  124. break;
  125. }
  126. return TRUE;
  127. }
  128. /* ----------------------------------------------------------------------- */
  129. static void warn(PluginInstance *This, char *fmt, ...)
  130. {
  131. va_list ap;
  132. char buf[2048];
  133. HWND hwnd;
  134. va_start(ap, fmt);
  135. wvsprintf(buf,fmt, ap);
  136. va_end(ap);
  137. if(This) hwnd= This->fhWnd;
  138. else hwnd=NULL;
  139. MessageBox(hwnd,buf,"MNG Plug-in",MB_OK|MB_ICONWARNING);
  140. }
  141. static void set_error(PluginInstance *This, char *fmt, ...)
  142. {
  143. va_list ap;
  144. char buf[2048];
  145. HWND hwnd;
  146. va_start(ap, fmt);
  147. wvsprintf(buf,fmt, ap);
  148. va_end(ap);
  149. if(This) hwnd= This->fhWnd;
  150. else hwnd=NULL;
  151. This->errorflag=1;
  152. lstrcpyn(This->errormsg,buf,256);
  153. if(This->lpdib) {
  154. free(This->lpdib);
  155. This->lpdib=NULL;
  156. }
  157. This->xscrollpos = This->yscrollpos = 0;
  158. if(This->fhWnd)
  159. InvalidateRect(This->fhWnd,NULL,TRUE);
  160. }
  161. /* ----------------------------------------------------------------------- */
  162. // MNG callbacks
  163. #define MNGPLG_CALLBACK MNG_DECL
  164. static mng_ptr MNGPLG_CALLBACK memallocfunc(mng_size_t n)
  165. {
  166. return (mng_ptr) calloc(n,1);
  167. }
  168. static void MNGPLG_CALLBACK memfreefunc(mng_ptr p, mng_size_t n)
  169. {
  170. free((void*)p);
  171. }
  172. static mng_bool MNGPLG_CALLBACK callback_openstream (mng_handle mng)
  173. {
  174. // PluginInstance *This;
  175. // This = (PluginInstance*) mng_get_userdata(mng);
  176. return MNG_TRUE;
  177. }
  178. static mng_bool MNGPLG_CALLBACK callback_closestream (mng_handle mng)
  179. {
  180. PluginInstance *This;
  181. This = (PluginInstance*) mng_get_userdata(mng);
  182. This->loadstate = STATE_LOADED; // this is probably redundant
  183. return MNG_TRUE;
  184. }
  185. static mng_bool MNGPLG_CALLBACK callback_readdata (mng_handle mng,mng_ptr pBuf,
  186. mng_uint32 Buflen,mng_uint32 *pRead)
  187. {
  188. int n;
  189. PluginInstance *This;
  190. This = (PluginInstance*) mng_get_userdata(mng);
  191. #ifdef MNGPLG_TRACE
  192. fprintf(tracefile,"readdata callback buflen=%d loadstate=%d bytesloaded=%d libmngpos=%d\n",
  193. Buflen,This->loadstate,This->bytesloaded, This->libmngpos);
  194. #endif
  195. // do we have enough data available?
  196. if(This->bytesloaded - This->libmngpos >= Buflen) {
  197. CopyMemory(pBuf,&This->mngdata[This->libmngpos],Buflen);
  198. (*pRead)= Buflen;
  199. This->libmngpos += Buflen;
  200. #ifdef MNGPLG_TRACE
  201. fprintf(tracefile,"returning full: %d\n",Buflen);
  202. #endif
  203. This->byteswanted=0;
  204. return MNG_TRUE;
  205. }
  206. else if(This->loadstate>=STATE_LOADED) {
  207. // We don't have the data it asked for, but we're at the end
  208. // of file, so send it anyway...?
  209. n=This->bytesloaded-This->libmngpos;
  210. if(n>0) {
  211. CopyMemory(pBuf,&This->mngdata[This->libmngpos],n);
  212. This->libmngpos+=n;
  213. }
  214. (*pRead)=n;
  215. // so what do we return?
  216. #ifdef MNGPLG_TRACE
  217. fprintf(tracefile,"returning partial: %d\n",n);
  218. #endif
  219. This->byteswanted=0;
  220. return MNG_TRUE;
  221. }
  222. // else we don't yet have the data it's requesting
  223. #ifdef MNGPLG_TRACE
  224. fprintf(tracefile,"returning 0\n");
  225. #endif
  226. (*pRead)=0;
  227. This->byteswanted=Buflen;
  228. return MNG_TRUE;
  229. }
  230. static mng_bool MNGPLG_CALLBACK callback_processheader(mng_handle mng,mng_uint32 iWidth,mng_uint32 iHeight)
  231. {
  232. PluginInstance *This;
  233. This = (PluginInstance*) mng_get_userdata(mng);
  234. This->diblinesize = (((iWidth * 24)+31)/32)*4;
  235. This->dibsize = sizeof(BITMAPINFOHEADER) + This->diblinesize*iHeight;
  236. This->lpdib = calloc(This->dibsize,1);
  237. This->lpdibinfo = (LPBITMAPINFOHEADER)This->lpdib;
  238. This->lpdibbits = &This->lpdib[sizeof(BITMAPINFOHEADER)];
  239. ZeroMemory((void*)This->lpdib,sizeof(BITMAPINFOHEADER));
  240. This->lpdibinfo->biSize = sizeof(BITMAPINFOHEADER);
  241. This->lpdibinfo->biWidth = iWidth;
  242. This->lpdibinfo->biHeight = iHeight;
  243. This->lpdibinfo->biPlanes = 1;
  244. This->lpdibinfo->biBitCount = 24;
  245. mng_set_canvasstyle (mng, MNG_CANVAS_BGR8);
  246. /* if(This->fhWnd) {
  247. if((int)iWidth > This->windowwidth || (int)iHeight > This->windowheight) {
  248. This->scrolling=1;
  249. }
  250. } */
  251. set_scrollbars(This);
  252. return MNG_TRUE;
  253. }
  254. static mng_ptr MNGPLG_CALLBACK callback_getcanvasline (mng_handle mng, mng_uint32 iLinenr)
  255. {
  256. unsigned char *pp;
  257. PluginInstance *This;
  258. This = (PluginInstance*) mng_get_userdata(mng);
  259. pp = (&This->lpdibbits[(This->lpdibinfo->biHeight-1-iLinenr)*This->diblinesize]);
  260. return (mng_ptr) pp;
  261. }
  262. static mng_bool MNGPLG_CALLBACK callback_refresh (mng_handle mng, mng_uint32 iLeft, mng_uint32 iTop,
  263. mng_uint32 iRight, mng_uint32 iBottom)
  264. {
  265. PluginInstance *This;
  266. RECT rect;
  267. This = (PluginInstance*) mng_get_userdata(mng);
  268. if(This->loadstate<STATE_VALIDFRAME) {
  269. This->loadstate=STATE_VALIDFRAME;
  270. }
  271. if(This->fhWnd) {
  272. if(This->paintedyet) {
  273. rect.left= iLeft - This->xscrollpos;
  274. rect.top= iTop - This->yscrollpos;
  275. rect.right= iLeft+iRight;
  276. rect.bottom= iTop+iBottom;
  277. InvalidateRect(This->fhWnd,&rect,FALSE);
  278. }
  279. else {
  280. // Make sure the first paint clears the whole plugin window
  281. InvalidateRect(This->fhWnd,NULL,TRUE);
  282. This->paintedyet=1;
  283. }
  284. UpdateWindow(This->fhWnd);
  285. }
  286. return MNG_TRUE;
  287. }
  288. static mng_uint32 MNGPLG_CALLBACK callback_gettickcount (mng_handle mng)
  289. {
  290. return GetTickCount();
  291. }
  292. static mng_bool MNGPLG_CALLBACK callback_settimer (mng_handle mng,mng_uint32 iMsecs)
  293. {
  294. PluginInstance *This;
  295. This = (PluginInstance*) mng_get_userdata(mng);
  296. if(This->fhWnd) {
  297. if(!SetTimer(This->fhWnd,1,(UINT)iMsecs,NULL)) {
  298. warn(This,"Unable to create a timer for animation");
  299. This->frozen=1;
  300. //return MNG_FALSE;
  301. return MNG_TRUE;
  302. }
  303. This->timer_set=1;
  304. }
  305. return MNG_TRUE;
  306. }
  307. static mng_bool MNGPLG_CALLBACK callback_processtext(mng_handle mng,
  308. mng_uint8 iType, mng_pchar zKeyword, mng_pchar zText,
  309. mng_pchar zLanguage, mng_pchar zTranslation)
  310. {
  311. PluginInstance *This;
  312. int pos,i;
  313. This = (PluginInstance*) mng_get_userdata(mng);
  314. if(!This->textdata) {
  315. This->textdata=(char*)malloc(MAXLEN_TEXT+10);
  316. if(!This->textdata) return MNG_TRUE;
  317. lstrcpy(This->textdata,"");
  318. }
  319. pos=lstrlen(This->textdata);
  320. if(pos>=(MAXLEN_TEXT-10)) return MNG_TRUE;
  321. if(pos>0) { /* separate items with a blank line */
  322. This->textdata[pos++]='\r';
  323. This->textdata[pos++]='\n';
  324. This->textdata[pos++]='\r';
  325. This->textdata[pos++]='\n';
  326. }
  327. for(i=0;zKeyword[i];i++) {
  328. if(pos<MAXLEN_TEXT)
  329. This->textdata[pos++]=zKeyword[i];
  330. }
  331. This->textdata[pos++]=':';
  332. This->textdata[pos++]=' ';
  333. for(i=0;zText[i];i++) {
  334. if(pos<MAXLEN_TEXT) {
  335. if(zText[i]=='\n') {
  336. This->textdata[pos++]='\r';
  337. }
  338. This->textdata[pos++]=zText[i];
  339. }
  340. }
  341. This->textdata[pos++]='\0';
  342. return MNG_TRUE;
  343. }
  344. #ifdef MNGPLG_TRACE
  345. static mng_bool MNGPLG_CALLBACK callback_traceproc (mng_handle mng,
  346. mng_int32 iFuncnr,
  347. mng_int32 iFuncseq,
  348. mng_pchar zFuncname)
  349. {
  350. if(tracefile) {
  351. fprintf(tracefile,"%d\t%d\t%d\t%s\n",(int)mng,iFuncnr,iFuncseq,zFuncname);
  352. }
  353. return MNG_TRUE;
  354. }
  355. #endif
  356. /* ----------------------------------------------------------------------- */
  357. static int file_exists(const char *fn)
  358. {
  359. HANDLE h;
  360. // try to open with no access
  361. h=CreateFile(fn,0,FILE_SHARE_READ,NULL,OPEN_EXISTING,
  362. FILE_ATTRIBUTE_NORMAL,NULL);
  363. if(h == INVALID_HANDLE_VALUE) { return 0; }
  364. CloseHandle(h);
  365. return 1;
  366. }
  367. static void handle_read_error(PluginInstance *This, mng_retcode rv)
  368. {
  369. mng_int8 iSeverity;
  370. mng_chunkid iChunkname;
  371. mng_uint32 iChunkseq;
  372. mng_int32 iExtra1;
  373. mng_int32 iExtra2;
  374. mng_pchar zErrortext;
  375. #ifdef MNGPLG_TRACE
  376. fprintf(tracefile,"returned: %d\n",rv);
  377. #endif
  378. switch(rv) {
  379. case MNG_NOERROR: case MNG_NEEDTIMERWAIT:
  380. break;
  381. case MNG_NEEDMOREDATA:
  382. if(This->loadstate>=STATE_LOADED) {
  383. set_error(This,"Unexpected end of file");
  384. }
  385. else {
  386. This->needresume=1;
  387. }
  388. break;
  389. case MNG_INVALIDSIG:
  390. set_error(This,"Invalid or missing MNG file (maybe a 404 Not Found error)");
  391. break;
  392. default:
  393. mng_getlasterror(This->mng, &iSeverity,&iChunkname,&iChunkseq,&iExtra1,
  394. &iExtra2,&zErrortext);
  395. if(zErrortext) {
  396. set_error(This,"Error reported by libmng (%d)\r\n\r\n%s",(int)rv,zErrortext);
  397. }
  398. else {
  399. set_error(This,"Error %d reported by libmng",(int)rv);
  400. }
  401. }
  402. }
  403. #ifdef MNGPLG_CMS
  404. static int init_color_management(PluginInstance *This)
  405. {
  406. mng_set_outputsrgb(This->mng);
  407. return 1;
  408. }
  409. #endif
  410. // return 1 if okay
  411. static int my_init_mng(PluginInstance *This)
  412. {
  413. mng_retcode rv;
  414. int err;
  415. This->mng = mng_initialize((mng_ptr)This,memallocfunc,memfreefunc,NULL);
  416. //(mng_memalloc) (mng_memfree)
  417. #ifdef MNGPLG_CMS
  418. init_color_management(This);
  419. #endif
  420. err=0;
  421. rv=mng_setcb_openstream (This->mng, callback_openstream ); if(rv) err++;
  422. rv=mng_setcb_closestream (This->mng, callback_closestream ); if(rv) err++;
  423. rv=mng_setcb_readdata (This->mng, callback_readdata ); if(rv) err++;
  424. rv=mng_setcb_processheader (This->mng, callback_processheader); if(rv) err++;
  425. rv=mng_setcb_getcanvasline (This->mng, callback_getcanvasline); if(rv) err++;
  426. rv=mng_setcb_refresh (This->mng, callback_refresh ); if(rv) err++;
  427. rv=mng_setcb_gettickcount (This->mng, callback_gettickcount ); if(rv) err++;
  428. rv=mng_setcb_settimer (This->mng, callback_settimer ); if(rv) err++;
  429. rv=mng_setcb_processtext (This->mng, callback_processtext ); if(rv) err++;
  430. #ifdef MNGPLG_TRACE
  431. rv=mng_setcb_traceproc (This->mng, callback_traceproc ); if(rv) err++;
  432. #endif
  433. if(err) {
  434. warn(This,"Error setting libmng callback functions");
  435. return 0;
  436. }
  437. rv= mng_set_suspensionmode (This->mng,MNG_TRUE);
  438. if(rv) {
  439. warn(This,"Error setting suspension mode");
  440. return 0;
  441. }
  442. // if the web page author provided a bgcolor, use it
  443. if(This->force_bgcolor) {
  444. rv=mng_set_bgcolor (This->mng, This->bg_r, This->bg_g, This->bg_b);
  445. }
  446. #ifdef MNGPLG_TRACE
  447. fprintf(tracefile,"initial readdisplay\n");
  448. #endif
  449. handle_read_error(This, mng_readdisplay(This->mng) );
  450. return 1;
  451. }
  452. /* Global initialization */
  453. static NPError NPP_Initialize(void)
  454. {
  455. if(!g_hInst) {
  456. warn(NULL,"MNG plugin error: Cannot load resources");
  457. }
  458. #ifdef MNGPLG_TRACE
  459. tracefile=fopen("c:\\temp\\mngtrace.txt","w");
  460. #endif
  461. #ifndef IDC_HAND
  462. #define IDC_HAND MAKEINTRESOURCE(32649)
  463. #endif
  464. hcurHandNS = LoadCursor(NULL,IDC_HAND);
  465. if(!hcurHandNS) {
  466. hcurHandNS=LoadCursor(g_hInst,"CURHAND_NS");
  467. }
  468. hfontMsg=CreateFont(-12,0,0,0,FW_DONTCARE,TRUE,0,0,ANSI_CHARSET,
  469. OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DRAFT_QUALITY,
  470. VARIABLE_PITCH|FF_SWISS,"Arial");
  471. return NPERR_NO_ERROR;
  472. }
  473. /* Global shutdown */
  474. static void NPP_Shutdown(void)
  475. {
  476. #ifdef MNGPLG_TRACE
  477. if(tracefile) {
  478. fclose(tracefile);
  479. tracefile=NULL;
  480. }
  481. #endif
  482. if(hfontMsg) DeleteObject((HGDIOBJ)hfontMsg);
  483. return;
  484. }
  485. static unsigned char gethex(const char *s)
  486. {
  487. int v[2];
  488. int i;
  489. v[0]=v[1]=0;
  490. for(i=0;i<2;i++) {
  491. if(s[i]>='a' && s[i]<='f') v[i]=s[i]-87;
  492. if(s[i]>='A' && s[i]<='F') v[i]=s[i]-55;
  493. if(s[i]>='0' && s[i]<='9') v[i]=s[i]-48;
  494. }
  495. return (unsigned char)(v[0]*16+v[1]);
  496. }
  497. static void hexcolor2rgb(const char *s, mng_uint16 *r, mng_uint16 *g, mng_uint16 *b)
  498. {
  499. if(lstrlen(s)!=7) return;
  500. if(s[0]!='#') return;
  501. (*r)= gethex(&s[1]); (*r)= ((*r)<<8)|(*r);
  502. (*g)= gethex(&s[3]); (*g)= ((*g)<<8)|(*g);
  503. (*b)= gethex(&s[5]); (*b)= ((*b)<<8)|(*b);
  504. }
  505. static void find_window_size(PluginInstance *This)
  506. {
  507. RECT r;
  508. if(This->scrolling) { // make sure scrollbars exist if needed
  509. ShowScrollBar(This->fhWnd,SB_BOTH,TRUE);
  510. }
  511. GetClientRect(This->fhWnd, &r);
  512. This->windowwidth=r.right;
  513. This->windowheight=r.bottom;
  514. }
  515. static void set_scrollbars(PluginInstance *This)
  516. {
  517. SCROLLINFO si;
  518. int maxpos;
  519. if(!This->scrolling) return;
  520. if(!This->fhWnd) return;
  521. ZeroMemory(&si,sizeof(SCROLLINFO));
  522. si.cbSize = sizeof(SCROLLINFO);
  523. // horizontal
  524. if(This->lpdib) {
  525. maxpos=This->lpdibinfo->biWidth-This->windowwidth;
  526. if(maxpos<0) maxpos=0;
  527. if(This->xscrollpos>maxpos) This->xscrollpos=maxpos;
  528. if(This->xscrollpos<0) This->xscrollpos=0;
  529. si.fMask = SIF_ALL|SIF_DISABLENOSCROLL;
  530. si.nMin = 0;
  531. si.nMax = This->lpdibinfo->biWidth -1;
  532. si.nPage = This->windowwidth;
  533. si.nPos = This->xscrollpos;
  534. }
  535. else { // no image to display
  536. si.fMask = SIF_ALL|SIF_DISABLENOSCROLL;
  537. si.nMin = 0;
  538. si.nMax = 0;
  539. si.nPage = 1;
  540. si.nPos = 0;
  541. }
  542. SetScrollInfo(This->fhWnd,SB_HORZ,&si,TRUE);
  543. // vertical
  544. if(This->lpdib) {
  545. maxpos=This->lpdibinfo->biHeight-This->windowheight;
  546. if(maxpos<0) maxpos=0;
  547. if(This->yscrollpos>maxpos) This->yscrollpos=maxpos;
  548. if(This->yscrollpos<0) This->yscrollpos=0;
  549. si.fMask = SIF_ALL|SIF_DISABLENOSCROLL;
  550. si.nMin = 0;
  551. si.nMax = This->lpdibinfo->biHeight -1;
  552. si.nPage = This->windowheight;
  553. si.nPos = This->yscrollpos;
  554. }
  555. SetScrollInfo(This->fhWnd,SB_VERT,&si,TRUE);
  556. }
  557. #define SCROLLLINE 40
  558. static void scrollmsg(PluginInstance *This, UINT msg,int code, short int pos)
  559. {
  560. int page;
  561. int dx, dy; // amount of scrolling
  562. int x_orig, y_orig;
  563. if(!This->scrolling) return;
  564. if(!This->lpdib) return;
  565. x_orig=This->xscrollpos;
  566. y_orig=This->yscrollpos;
  567. if(msg==WM_HSCROLL) {
  568. page=This->windowwidth-15;
  569. if(page<SCROLLLINE) page=SCROLLLINE;
  570. switch(code) {
  571. case SB_LINELEFT: This->xscrollpos-=SCROLLLINE; break;
  572. case SB_LINERIGHT: This->xscrollpos+=SCROLLLINE; break;
  573. case SB_PAGELEFT: This->xscrollpos-=page; break;
  574. case SB_PAGERIGHT: This->xscrollpos+=page; break;
  575. case SB_LEFT: This->xscrollpos=0; break;
  576. case SB_RIGHT: This->xscrollpos=This->lpdibinfo->biWidth; break;
  577. case SB_THUMBTRACK: This->xscrollpos=pos; break;
  578. default: return;
  579. }
  580. set_scrollbars(This);
  581. }
  582. else if(msg==WM_VSCROLL) {
  583. page=This->windowheight-15;
  584. if(page<SCROLLLINE) page=SCROLLLINE;
  585. switch(code) {
  586. case SB_LINEUP: This->yscrollpos-=SCROLLLINE; break;
  587. case SB_LINEDOWN: This->yscrollpos+=SCROLLLINE; break;
  588. case SB_PAGEUP: This->yscrollpos-=page; break;
  589. case SB_PAGEDOWN: This->yscrollpos+=page; break;
  590. case SB_TOP: This->yscrollpos=0; break;
  591. case SB_BOTTOM: This->yscrollpos=This->lpdibinfo->biHeight; break;
  592. case SB_THUMBTRACK: This->yscrollpos=pos; break;
  593. default: return;
  594. }
  595. set_scrollbars(This);
  596. }
  597. dx= x_orig - This->xscrollpos;
  598. dy= y_orig - This->yscrollpos;
  599. if(dx || dy) { // if any change
  600. // GetClientRect(This->fhWnd,&cliprect);
  601. ScrollWindowEx(This->fhWnd,dx,dy,NULL,NULL /*&cliprect*/,NULL,NULL,SW_INVALIDATE);
  602. }
  603. }
  604. /* Once-per-instance initialization */
  605. static NPError NPP_New(NPMIMEType pluginType,NPP instance,uint16 mode,
  606. int16 argc,char* argn[],char* argv[],NPSavedData* saved)
  607. {
  608. PluginInstance* This;
  609. int i;
  610. if (instance == NULL) {
  611. return NPERR_INVALID_INSTANCE_ERROR;
  612. }
  613. instance->pdata = calloc(sizeof(PluginInstance),1);
  614. This = (PluginInstance*) instance->pdata;
  615. if (This == NULL) {
  616. return NPERR_OUT_OF_MEMORY_ERROR;
  617. }
  618. This->force_bgcolor=1;
  619. This->bg_r = This->bg_g = This->bg_b = 0xffff;
  620. /* record some info for later lookup */
  621. This->fWindow = NULL;
  622. This->fMode = mode;
  623. This->fhWnd = NULL;
  624. This->fDefaultWindowProc = NULL;
  625. This->instance = instance; /* save the instance id for reverse lookups */
  626. This->scrolling = (mode==NP_FULL);
  627. This->xscrollpos = This->yscrollpos = 0;
  628. This->windowwidth = This->windowheight = 0;
  629. This->loadstate = STATE_INIT;
  630. This->paintedyet = 0;
  631. This->mng=0;
  632. This->lpdib=NULL;
  633. lstrcpy(This->url,"");
  634. This->frozen=0;
  635. This->needresume=0;
  636. This->errorflag=0;
  637. lstrcpy(This->errormsg,"");
  638. This->dibsize = This->filesize = 0;
  639. lstrcpy(This->linkurl,"");
  640. lstrcpy(This->linktarget,"_self");
  641. This->islink=0;
  642. This->timer_set=0;
  643. This->timer2_set=0;
  644. This->dynamicmng= -1;
  645. This->mouse_over_mng=0;
  646. This->mouse_captured=0;
  647. This->linkcursor = hcurHandNS;
  648. // examine the <embed> tag arguments
  649. for(i=0;i<argc;i++) {
  650. if(!_stricmp(argn[i],"bgcolor")) {
  651. This->force_bgcolor=1;
  652. hexcolor2rgb(argv[i],&This->bg_r,&This->bg_g,&This->bg_b);
  653. }
  654. else if(!_stricmp(argn[i],"href")) {
  655. lstrcpyn(This->linkurl,argv[i],MAXLEN_URL);
  656. This->islink=1;
  657. }
  658. else if(!_stricmp(argn[i],"target")) {
  659. lstrcpyn(This->linktarget,argv[i],MAXLEN_TARGET);
  660. }
  661. }
  662. This->bkgdbrush=NULL;
  663. if(This->force_bgcolor)
  664. This->bkgdbrush=CreateSolidBrush(RGB(This->bg_r,This->bg_g,This->bg_b));
  665. return NPERR_NO_ERROR;
  666. }
  667. static void BeforeDestroyWindow(PluginInstance *This)
  668. {
  669. if(This->timer_set) {
  670. KillTimer(This->fhWnd,1);
  671. This->timer_set=0;
  672. }
  673. if(This->timer2_set) {
  674. KillTimer(This->fhWnd,2);
  675. This->timer2_set=0;
  676. }
  677. if(This->mouse_captured) {
  678. ReleaseCapture();
  679. This->mouse_captured=0;
  680. }
  681. SetWindowLong( This->fhWnd, GWL_WNDPROC, (LONG)This->fDefaultWindowProc); // unsubclass
  682. This->fDefaultWindowProc = NULL;
  683. This->fhWnd = NULL;
  684. }
  685. static NPError NPP_Destroy(NPP instance, NPSavedData** save)
  686. {
  687. PluginInstance* This;
  688. if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR;
  689. This = (PluginInstance*) instance->pdata;
  690. if(!This) return NPERR_INVALID_INSTANCE_ERROR;
  691. if(This->mng) {
  692. This->dynamicmng=0;
  693. mng_cleanup(&This->mng);
  694. This->mng=0;
  695. }
  696. if(This->lpdib) {
  697. free(This->lpdib);
  698. This->lpdib=NULL;
  699. }
  700. if(This->mngdata) {
  701. free(This->mngdata);
  702. This->mngdata=NULL;
  703. This->bytesalloc=0;
  704. }
  705. if(This->textdata) {
  706. free(This->textdata);
  707. This->textdata=NULL;
  708. }
  709. if( This->fhWnd ) { // un-subclass the plugin window
  710. BeforeDestroyWindow(This);
  711. }
  712. if(This->bkgdbrush) DeleteObject((HGDIOBJ)This->bkgdbrush);
  713. if(This) {
  714. if(instance->pdata) free(instance->pdata);
  715. instance->pdata = NULL;
  716. }
  717. return NPERR_NO_ERROR;
  718. }
  719. /* Browser is providing us with a window */
  720. static NPError NPP_SetWindow(NPP instance, NPWindow* window)
  721. {
  722. NPError result = NPERR_NO_ERROR;
  723. PluginInstance* This;
  724. if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR;
  725. This = (PluginInstance*) instance->pdata;
  726. if( This->fhWnd != NULL ) { /* If we already have a window... */
  727. if( (window == NULL) || ( window->window == NULL ) ) {
  728. /* There is now no window to use. get rid of the old
  729. * one and exit. */
  730. BeforeDestroyWindow(This);
  731. This->fWindow=window;
  732. return NPERR_NO_ERROR;
  733. }
  734. else if ( This->fhWnd == (HWND) window->window ) {
  735. /* The new window is the same as the old one. Redraw and get out. */
  736. This->fWindow=window;
  737. InvalidateRect( This->fhWnd, NULL, FALSE );
  738. /* UpdateWindow( This->fhWnd ); */
  739. return NPERR_NO_ERROR;
  740. }
  741. else {
  742. /* Unsubclass the old window, so that we can subclass the new
  743. * one later. */
  744. BeforeDestroyWindow(This);
  745. }
  746. }
  747. else if( (window == NULL) || ( window->window == NULL ) ) {
  748. /* We can just get out of here if there is no current
  749. * window and there is no new window to use. */
  750. This->fWindow=window;
  751. return NPERR_NO_ERROR;
  752. }
  753. /* Subclass the new window so that we can begin drawing and
  754. * receiving window messages. */
  755. This->fDefaultWindowProc = (WNDPROC)SetWindowLong( (HWND)window->window, GWL_WNDPROC, (LONG)PluginWindowProc);
  756. This->fhWnd = (HWND) window->window;
  757. SetProp( This->fhWnd, gInstanceLookupString, (HANDLE)This);
  758. This->fWindow = window;
  759. find_window_size(This);
  760. set_scrollbars(This);
  761. InvalidateRect( This->fhWnd, NULL, TRUE );
  762. UpdateWindow( This->fhWnd );
  763. return result;
  764. }
  765. // browser is announcing its intent to send data to us
  766. static NPError NPP_NewStream(NPP instance,NPMIMEType type,NPStream *stream,
  767. NPBool seekable,uint16 *stype) {
  768. PluginInstance* This;
  769. if(instance==NULL)
  770. return NPERR_INVALID_INSTANCE_ERROR;
  771. This = (PluginInstance*) instance->pdata;
  772. if(!This)
  773. return NPERR_GENERIC_ERROR;
  774. /* save the URL for later */
  775. lstrcpyn(This->url,stream->url,MAX_PATH);
  776. This->libmngpos=0;
  777. This->bytesloaded=0;
  778. This->bytesalloc=0;
  779. This->byteswanted=0;
  780. This->mngdata=NULL;
  781. This->textdata=NULL;
  782. // if we know the total length of the stream in advance
  783. // (most of the time we will, hopefully), allocate that amount.
  784. if(stream->end > 0) {
  785. This->mngdata = malloc(stream->end);
  786. This->bytesalloc= stream->end;
  787. }
  788. my_init_mng(This);
  789. This->loadstate=STATE_LOADING;
  790. (*stype)=NP_NORMAL;
  791. return NPERR_NO_ERROR;
  792. }
  793. static int32 NPP_WriteReady(NPP instance, NPStream *stream)
  794. {
  795. /* Number of bytes ready to accept in NPP_Write() */
  796. /* We can handle any amount, so just return some really big number. */
  797. return (int32)0X0FFFFFFF;
  798. }
  799. #define ALLOC_CHUNK_SIZE 131072
  800. static int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
  801. {
  802. PluginInstance* This;
  803. #ifdef MNGPLG_TRACE
  804. fprintf(tracefile,"NPP_Write offs=%d len=%d\n",offset,len);
  805. #endif
  806. if(!instance) return -1;
  807. This = (PluginInstance*) instance->pdata;
  808. if(!This) return -1;
  809. if(len<1) return len;
  810. if(offset+len > (int)This->bytesalloc) { // oops, overflowed our memory buffer
  811. This->bytesalloc += ALLOC_CHUNK_SIZE;
  812. if(This->mngdata) {
  813. This->mngdata=realloc(This->mngdata, This->bytesalloc);
  814. }
  815. else { // first time
  816. This->mngdata=malloc(This->bytesalloc);
  817. }
  818. if(!This->mngdata) {
  819. warn(This,"Cannot allocate memory for image (%d,%d,%p",offset,len,buffer);
  820. return -1;
  821. }
  822. }
  823. // now we should have enough room to copy the data to memory
  824. CopyMemory(&This->mngdata[offset],buffer,len);
  825. This->bytesloaded = offset+len;
  826. // now, check if it's time to call mng_read_resume
  827. if(This->needresume &&
  828. (This->bytesloaded >= (This->libmngpos + This->byteswanted)) )
  829. {
  830. This->needresume=0;
  831. // handle_read_error(This, mng_read_resume(This->mng) );
  832. #ifdef MNGPLG_TRACE
  833. fprintf(tracefile,"NPP_Write display_resume bytesloaded=%d libmngpos=%d byteswanted=%d\n",
  834. This->bytesloaded,This->libmngpos,This->byteswanted);
  835. #endif
  836. handle_read_error(This, mng_display_resume(This->mng) );
  837. }
  838. return len; // The number of bytes accepted -- we always accept them all.
  839. }
  840. /* DestroyStream gets called after the file has finished loading,
  841. */
  842. static NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
  843. {
  844. PluginInstance* This;
  845. if(!instance) return NPERR_INVALID_INSTANCE_ERROR;
  846. This = (PluginInstance*) instance->pdata;
  847. // if(reason==NPRES_DONE) {
  848. This->filesize = This->bytesloaded;
  849. This->loadstate = STATE_LOADED;
  850. // }
  851. if(reason!=NPRES_DONE) {
  852. set_error(This,"Image load failed or was canceled (%d)",(int)reason);
  853. This->needresume=0;
  854. if(This->timer_set) { KillTimer(This->fhWnd,1); This->timer_set=0; }
  855. return NPERR_NO_ERROR;
  856. }
  857. #ifdef MNGPLG_TRACE
  858. fprintf(tracefile,"NPP_DestroyStream reason=%d needresume=%d\n",reason,This->needresume);
  859. #endif
  860. if(This->needresume) {
  861. This->needresume=0;
  862. // handle_read_error(This, mng_read_resume(This->mng) );
  863. handle_read_error(This, mng_display_resume(This->mng) );
  864. // This->needresume=0;
  865. }
  866. return NPERR_NO_ERROR;
  867. }
  868. static void NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
  869. {
  870. return;
  871. }
  872. // Print embedded plug-in (via the browser's Print command)
  873. static void NPP_Print(NPP instance, NPPrint* printInfo)
  874. {
  875. PluginInstance* This;
  876. if (instance == NULL) return;
  877. This = (PluginInstance*) instance->pdata;
  878. if(printInfo == NULL) {
  879. // Some browsers (Netscape) set printInfo to NULL to tell the plugin
  880. // to print in full page mode (this may be a bug).
  881. // PrintFullPage(); -- full page printing not implemented
  882. return;
  883. }
  884. if (printInfo->mode == NP_FULL) {
  885. /* the plugin is full-page, and the browser is giving it a chance
  886. * to print in the manner of its choosing */
  887. void* platformPrint = printInfo->print.fullPrint.platformPrint;
  888. NPBool printOne = printInfo->print.fullPrint.printOne;
  889. /* Setting this to FALSE and returning *should* cause the browser to
  890. * call NPP_Print again, this time with mode=NP_EMBED.
  891. * However, that doesn't happen with any browser I've ever seen :-(.
  892. * Instead of the following line, you will probably need to implement
  893. * printing yourself. You also might as well set pluginPrinted to TRUE,
  894. * though every browser I've tested ignores it. */
  895. printInfo->print.fullPrint.pluginPrinted = FALSE;
  896. /* or */
  897. /* PrintFullPage();
  898. * printInfo->print.fullPrint.pluginPrinted = TRUE; */
  899. }
  900. else { // we are embedded, and the browser had provided a printer context
  901. HDC pdc;
  902. int prevstretchmode;
  903. NPWindow* printWindow;
  904. if(This->loadstate < STATE_VALIDFRAME) return;
  905. printWindow= &(printInfo->print.embedPrint.window);
  906. /* embedPrint.platformPrint is a Windows device context in disguise */
  907. /* The definition of NPWindow changed between API verion 0.9 and 0.11,
  908. * increasing in size from 28 to 32 bytes. This normally makes it
  909. * impossible for version 0.9 browsers to print version 0.11 plugins
  910. * (because the platformPrint field ends up at the wrong offset) --
  911. * unless the plugin takes special care to detect this situation.
  912. * To work around it, if we are compiled with API 0.11 or higher,
  913. * and the browser is version 0.9 or earlier, we look for the HDC
  914. * 4 bytes earlier, at offset 28 instead of 32 (of the embedPrint
  915. * sub-structure).
  916. */
  917. if(sizeof(NPWindow)>28 && /* i.e. is plugin API >= 0.11? */
  918. HIBYTE(g_pNavigatorFuncs->version)==0 &&
  919. LOBYTE(g_pNavigatorFuncs->version)<=9) {
  920. char *tmpc;
  921. HDC *tmph;
  922. tmpc= (char*)&(printInfo->print.embedPrint);
  923. tmph= (HDC*)&tmpc[28];
  924. pdc= *tmph;
  925. }
  926. else {
  927. pdc= (HDC) (printInfo->print.embedPrint.platformPrint);
  928. }
  929. if(!This->lpdib) return;
  930. prevstretchmode=SetStretchBltMode(pdc,COLORONCOLOR);
  931. StretchDIBits(pdc,
  932. printWindow->x,printWindow->y,
  933. printWindow->width,printWindow->height, /* dest coords */
  934. 0,0,This->lpdibinfo->biWidth, This->lpdibinfo->biHeight, /* source coords */
  935. This->lpdibbits, (LPBITMAPINFO)This->lpdib,
  936. DIB_RGB_COLORS,SRCCOPY);
  937. if(prevstretchmode) SetStretchBltMode(pdc,prevstretchmode);
  938. }
  939. return;
  940. }
  941. /*+++++++++++++++++++++++++++++++++++++++++++++++++
  942. * NPP_URLNotify:
  943. * Notifies the instance of the completion of a URL request.
  944. +++++++++++++++++++++++++++++++++++++++++++++++++*/
  945. static void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
  946. {
  947. return;
  948. }
  949. /**********************************************************************/
  950. /* Try to make a filename from the url. Caller must provide fn[MAX_PATH] buffer.
  951. * This function attempts to extract a bitmap filename from a URL,
  952. * but if it doesn't look like it contains an appropriate name,
  953. * it leaves it blank. */
  954. static void url2filename(char *fn, char *url)
  955. {
  956. int title,ext,i;
  957. lstrcpy(fn,"");
  958. ext=0; /* position of the file extention */
  959. title=0; /* position of the base filename */
  960. for(i=0;url[i];i++) {
  961. if(url[i]=='.') ext=i+1;
  962. if(url[i]=='/') title=i+1;
  963. if(url[i]=='\\') title=i+1; // handle Microsoft's bogus file: "URLs"
  964. if(url[i]==':') title=i+1;
  965. if(url[i]=='=') title=i+1;
  966. }
  967. if (!_stricmp(&url[ext],"mng") ||
  968. !_stricmp(&url[ext],"jng") ||
  969. !_stricmp(&url[ext],"png") )
  970. {
  971. lstrcpyn(fn,&url[title],MAX_PATH);
  972. }
  973. }
  974. // sanitize string and escape '&'s for use in a menu
  975. static void escapeformenu(unsigned char *s1)
  976. {
  977. int f, t, len;
  978. unsigned char s2[200];
  979. t=0;
  980. len=lstrlen(s1); if(len>50) len=50;
  981. for(f=0;f<len;f++) {
  982. if(s1[f]=='&') {
  983. s2[t++]='&';
  984. s2[t++]='&';
  985. }
  986. else if(s1[f]<32) {
  987. s2[t++]='_';
  988. }
  989. else {
  990. s2[t++]=s1[f];
  991. }
  992. }
  993. s2[t]='\0';
  994. lstrcpy(s1,s2);
  995. }
  996. static char *get_imagetype_name(mng_imgtype t)
  997. {
  998. switch(t) {
  999. case mng_it_mng: return "MNG";
  1000. case mng_it_png: return "PNG";
  1001. case mng_it_jng: return "JNG";
  1002. }
  1003. return "Unknown";
  1004. }
  1005. /* Write the image to a local file */
  1006. static void SaveImage(PluginInstance *This)
  1007. {
  1008. OPENFILENAME ofn;
  1009. char fn[MAX_PATH];
  1010. HANDLE hfile;
  1011. BOOL b;
  1012. mng_imgtype t;
  1013. DWORD byteswritten;
  1014. if(!This->mng || This->loadstate<STATE_LOADED ||
  1015. This->bytesloaded != This->filesize)
  1016. {
  1017. warn(This,"Image not loaded -- can't save");
  1018. return;
  1019. }
  1020. if(lstrlen(This->url)) {
  1021. url2filename(fn,This->url);
  1022. }
  1023. else {
  1024. lstrcpy(fn,"");
  1025. }
  1026. ZeroMemory(&ofn,sizeof(OPENFILENAME));
  1027. ofn.lStructSize=sizeof(OPENFILENAME);
  1028. ofn.hwndOwner=This->fhWnd;
  1029. ofn.nFilterIndex=1;
  1030. ofn.lpstrTitle="Save Image As...";
  1031. ofn.lpstrFile=fn;
  1032. ofn.nMaxFile=MAX_PATH;
  1033. ofn.Flags=OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
  1034. t=mng_get_sigtype(This->mng);
  1035. if(t==mng_it_png) {
  1036. ofn.lpstrDefExt="png"; // FIXME also give an option of MNG
  1037. ofn.lpstrFilter="PNG (*.png)\0*.png\0\0";
  1038. }
  1039. else if(t==mng_it_jng) {
  1040. ofn.lpstrDefExt="jng"; // FIXME also give an option of MNG
  1041. ofn.lpstrFilter="JNG (*.jng)\0*.jng\0\0";
  1042. }
  1043. else {
  1044. ofn.lpstrFilter="MNG (*.mng)\0*.mng\0\0";
  1045. ofn.lpstrDefExt="mng";
  1046. }
  1047. if(GetSaveFileName(&ofn)) {
  1048. // save to filename: ofn.lpstrFile
  1049. hfile=CreateFile(ofn.lpstrFile,GENERIC_WRITE,FILE_SHARE_READ,
  1050. NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  1051. if(hfile==INVALID_HANDLE_VALUE) {
  1052. warn(This,"Unable to write file");
  1053. }
  1054. else {
  1055. b=WriteFile(hfile, This->mngdata, This->filesize,
  1056. &byteswritten,NULL);
  1057. if(!b || byteswritten != This->filesize) {
  1058. warn(This,"Error writing file");
  1059. }
  1060. CloseHandle(hfile);
  1061. }
  1062. }
  1063. }
  1064. static void CopyToClipboard(PluginInstance *This,unsigned char *mem,int size,UINT format)
  1065. {
  1066. HGLOBAL hClip;
  1067. LPVOID lpClip;
  1068. if(!mem) return;
  1069. if(!OpenClipboard(NULL)) {
  1070. warn(This,"Can't open the clipboard");
  1071. return;
  1072. }
  1073. if(EmptyClipboard()) {
  1074. hClip=GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,size);
  1075. lpClip=GlobalLock(hClip);
  1076. if(lpClip) {
  1077. CopyMemory(lpClip,mem,size);
  1078. GlobalUnlock(hClip);
  1079. if(!SetClipboardData(format,hClip)) {
  1080. warn(This,"Can't set clipboard data");
  1081. }
  1082. }
  1083. else {
  1084. warn(This,"Can't allocate memory for clipboard");
  1085. }
  1086. }
  1087. else {
  1088. warn(This,"Can't clear the clipboard");
  1089. }
  1090. CloseClipboard();
  1091. }
  1092. static void AboutDialog(PluginInstance *This)
  1093. {
  1094. DialogBoxParam(g_hInst,"ABOUTDLG",This->fhWnd,(DLGPROC)DlgProcAbout,(LPARAM)This);
  1095. }
  1096. static void PropDialog(PluginInstance *This)
  1097. {
  1098. //if(This->textdata)
  1099. DialogBoxParam(g_hInst,"PROPDLG",This->fhWnd,(DLGPROC)DlgProcProp,(LPARAM)This);
  1100. }
  1101. static void display_last_error(PluginInstance *This)
  1102. {
  1103. if(This->errorflag) {
  1104. warn(This,"%s",This->errormsg);
  1105. }
  1106. }
  1107. static void DynamicMNG_FireEvent(PluginInstance *This, mng_uint8 eventtype, POINTS pos)
  1108. {
  1109. mng_retcode r;
  1110. if(!This->mng) return;
  1111. if(This->dynamicmng == 0) return;
  1112. if(This->dynamicmng == -1) {
  1113. r=mng_status_dynamic(This->mng);
  1114. if(r==MNG_FALSE) {
  1115. return;
  1116. }
  1117. else {
  1118. This->dynamicmng=1;
  1119. }
  1120. }
  1121. mng_trapevent(This->mng, eventtype, pos.x+This->xscrollpos, pos.y+This->yscrollpos);
  1122. }
  1123. static void ContextMenu(PluginInstance *This, HWND hwnd)
  1124. {
  1125. int cmd;
  1126. HMENU menu;
  1127. POINT pt;
  1128. unsigned char buf[MAX_PATH], buf2[200];
  1129. pt.x=0; pt.y=0;
  1130. GetCursorPos(&pt);
  1131. // create context menu dynamically
  1132. menu=CreatePopupMenu();
  1133. if(This->errorflag) {
  1134. AppendMenu(menu,MF_ENABLED,ID_SHOWERROR,"SHOW ERROR MESSAGE");
  1135. AppendMenu(menu,MF_SEPARATOR,0,NULL);
  1136. }
  1137. AppendMenu(menu,(This->loadstate>=STATE_LOADED?MF_ENABLED:MF_GRAYED),ID_SAVEAS,"Save Image &As...");
  1138. AppendMenu(menu,(This->lpdib?MF_ENABLED:MF_GRAYED),ID_COPYIMAGE,"&Copy Image");
  1139. AppendMenu(menu,MF_ENABLED,ID_COPYURL,"Cop&y Image Location");
  1140. if(This->islink) {
  1141. AppendMenu(menu,MF_ENABLED,ID_COPYLINKLOC,"Copy Link Location");
  1142. }
  1143. url2filename(buf,This->url);
  1144. escapeformenu(buf);
  1145. if(lstrlen(buf)) {
  1146. wsprintf(buf2,"View Image (%s)",buf);
  1147. }
  1148. else {
  1149. wsprintf(buf2,"View Image");
  1150. }
  1151. AppendMenu(menu,MF_ENABLED,ID_VIEWIMAGE,buf2);
  1152. AppendMenu(menu,MF_SEPARATOR,0,NULL);
  1153. // AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED),ID_STOPANIM,"Stop Animation");
  1154. AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED)|
  1155. (This->frozen?MF_CHECKED:MF_UNCHECKED),ID_FREEZE,"&Freeze Animation");
  1156. // AppendMenu(menu,(This->mng?MF_ENABLED:MF_GRAYED),ID_RESTARTANIM,"Restart Animation");
  1157. AppendMenu(menu,MF_SEPARATOR,0,NULL);
  1158. AppendMenu(menu,MF_ENABLED,ID_PROPERTIES,"Properties...");
  1159. AppendMenu(menu,MF_ENABLED,ID_ABOUT,"About MNG Plug-in...");
  1160. cmd=TrackPopupMenuEx(menu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_NONOTIFY|TPM_RETURNCMD|
  1161. TPM_RIGHTBUTTON,pt.x,pt.y,hwnd,NULL);
  1162. DestroyMenu(menu);
  1163. switch(cmd) {
  1164. case ID_STOPANIM:
  1165. if(This->mng) {
  1166. KillTimer(This->fhWnd,1);
  1167. This->timer_set=0;
  1168. mng_display_freeze(This->mng);
  1169. }
  1170. break;
  1171. case ID_FREEZE:
  1172. This->frozen = !This->frozen;
  1173. if(This->frozen) {
  1174. KillTimer(This->fhWnd,1);
  1175. This->timer_set=0;
  1176. mng_display_freeze(This->mng);
  1177. }
  1178. else {
  1179. handle_read_error(This, mng_display_resume(This->mng) );
  1180. }
  1181. break;
  1182. case ID_RESTARTANIM:
  1183. if(!This->frozen) {
  1184. KillTimer(This->fhWnd,1);
  1185. This->timer_set=0;
  1186. mng_display_freeze(This->mng);
  1187. }
  1188. This->frozen=1;
  1189. mng_display_reset(This->mng);
  1190. This->frozen=0;
  1191. handle_read_error(This, mng_display_resume(This->mng) );
  1192. break;
  1193. case ID_SAVEAS:
  1194. SaveImage(This);
  1195. break;
  1196. case ID_COPYIMAGE:
  1197. if(This->lpdib) {
  1198. CopyToClipboard(This,(unsigned char*)This->lpdib,This->dibsize,CF_DIB);
  1199. }
  1200. else {
  1201. warn(This,"No image to copy");
  1202. }
  1203. break;
  1204. case ID_COPYURL:
  1205. CopyToClipboard(This,This->url,lstrlen(This->url)+1,CF_TEXT);
  1206. break;
  1207. case ID_COPYLINKLOC:
  1208. if(This->islink) {
  1209. CopyToClipboard(This,This->linkurl,lstrlen(This->linkurl)+1,CF_TEXT);
  1210. }
  1211. break;
  1212. case ID_VIEWIMAGE:
  1213. if(lstrlen(This->url))
  1214. NPN_GetURL(This->instance,This->url,"_self");
  1215. break;
  1216. case ID_PROPERTIES:
  1217. PropDialog(This);
  1218. break;
  1219. case ID_ABOUT:
  1220. AboutDialog(This);
  1221. break;
  1222. case ID_SHOWERROR:
  1223. display_last_error(This);
  1224. break;
  1225. }
  1226. }
  1227. /*+++++++++++++++++++++++++++++++++++++++++++++++++
  1228. * PluginWindowProc
  1229. * Handle the Windows window-event loop.
  1230. +++++++++++++++++++++++++++++++++++++++++++++++++*/
  1231. static LRESULT CALLBACK PluginWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  1232. {
  1233. PluginInstance* This;
  1234. HDC hdc;
  1235. RECT rect;
  1236. This = (PluginInstance*) GetProp(hWnd, gInstanceLookupString);
  1237. if(!This) return DefWindowProc( hWnd, Msg, wParam, lParam);
  1238. switch(Msg) {
  1239. case WM_ERASEBKGND:
  1240. {
  1241. HBRUSH br;
  1242. hdc= (HDC)wParam;
  1243. if(This->bkgdbrush)
  1244. br=This->bkgdbrush;
  1245. else
  1246. br=GetStockObject(GRAY_BRUSH);
  1247. GetClientRect(hWnd,&rect);
  1248. FillRect(hdc,&rect,br);
  1249. return 1;
  1250. }
  1251. case WM_HSCROLL:
  1252. case WM_VSCROLL:
  1253. scrollmsg(This,Msg,(int)(LOWORD(wParam)),(short int)(HIWORD(wParam)));
  1254. return 0;
  1255. case WM_SIZE:
  1256. find_window_size(This);
  1257. set_scrollbars(This);
  1258. return 0;
  1259. case WM_CONTEXTMENU: case WM_RBUTTONUP:
  1260. ContextMenu(This, hWnd);
  1261. return 0;
  1262. case WM_SETCURSOR:
  1263. if(LOWORD(lParam)==HTCLIENT) {
  1264. if(This->islink) {
  1265. SetCursor(This->linkcursor);
  1266. return 1;
  1267. }
  1268. }
  1269. break;
  1270. case WM_LBUTTONDOWN:
  1271. SetCapture(This->fhWnd);
  1272. This->mouse_captured=1;
  1273. if(This->dynamicmng && This->mng && !This->errorflag) {
  1274. DynamicMNG_FireEvent(This,4,MAKEPOINTS(lParam));
  1275. }
  1276. return 0;
  1277. case WM_LBUTTONUP:
  1278. {
  1279. RECT rc;
  1280. POINT pt;
  1281. if(This->mouse_captured) {
  1282. ReleaseCapture();
  1283. This->mouse_captured=0;
  1284. }
  1285. if(This->dynamicmng && This->mng && !This->errorflag) {
  1286. DynamicMNG_FireEvent(This,5,MAKEPOINTS(lParam));
  1287. }
  1288. // if mouse is not over image, don't follow links, etc.
  1289. GetWindowRect(This->fhWnd,&rc);
  1290. GetCursorPos(&pt);
  1291. if(!PtInRect(&rc,pt)) return 0;
  1292. if(This->islink) {
  1293. NPN_GetURL(This->instance,This->linkurl,This->linktarget);
  1294. return 0;
  1295. }
  1296. else if(This->errorflag) {
  1297. display_last_error(This);
  1298. }
  1299. }
  1300. return 0;
  1301. case WM_MOUSEMOVE:
  1302. if(This->dynamicmng && This->mng && This->lpdib && !This->errorflag) {
  1303. POINTS pos;
  1304. int overimage;
  1305. pos=MAKEPOINTS(lParam);
  1306. overimage=0;
  1307. if(pos.x>=0 && pos.x<This->lpdibinfo->biWidth && pos.y>=0 && pos.y<This->lpdibinfo->biHeight) {
  1308. overimage=1;
  1309. }
  1310. if(overimage) {
  1311. if(This->mouse_over_mng) {
  1312. // mouse is still over image: mouse move event
  1313. DynamicMNG_FireEvent(This,2,pos); // 2=mouse move
  1314. }
  1315. else {
  1316. // mouse wasn't over the image but now it is: mouse-enter event
  1317. DynamicMNG_FireEvent(This,1,pos); // mouse enter
  1318. }
  1319. }
  1320. else { // mouse not now over image
  1321. if(This->mouse_over_mng) { // ... but it used to be
  1322. pos.x=0; pos.y=0;
  1323. DynamicMNG_FireEvent(This,3,pos); // 3=mouse leave
  1324. }
  1325. }
  1326. This->mouse_over_mng=overimage; // remember for next time
  1327. if(This->mouse_over_mng && (This->dynamicmng==1) ) {
  1328. #define MOUSE_POLL_INTERVAL 100 // milliseconds
  1329. SetTimer(This->fhWnd,2,MOUSE_POLL_INTERVAL,NULL);
  1330. This->timer2_set=0;
  1331. }
  1332. }
  1333. return 0;
  1334. case WM_PAINT:
  1335. {
  1336. PAINTSTRUCT paintStruct;
  1337. HDC hdc;
  1338. RECT rect2;
  1339. hdc = BeginPaint( hWnd, &paintStruct );
  1340. SetWindowOrgEx(hdc,This->xscrollpos,This->yscrollpos,NULL);
  1341. GetClientRect(hWnd,&rect);
  1342. if(This) {
  1343. if(This->errorflag || !This->lpdib) {
  1344. SelectObject(hdc,hfontMsg);
  1345. Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);
  1346. rect2.left=rect.left+2;
  1347. rect2.top=rect.top+2;
  1348. rect2.right=rect.right-2;
  1349. rect2.bottom=rect.bottom-2;
  1350. if(This->errorflag) {
  1351. DrawText(hdc,"MNG PLUG-IN ERROR!",-1,&rect2,DT_LEFT|DT_WORDBREAK);
  1352. }
  1353. else {
  1354. if(This->loadstate>=STATE_LOADING) {
  1355. DrawText(hdc,"MNG image loading...",-1,&rect2,DT_LEFT|DT_WORDBREAK);
  1356. }
  1357. else {
  1358. DrawText(hdc,"MNG plug-in",-1,&rect2,DT_LEFT|DT_WORDBREAK);
  1359. }
  1360. }
  1361. }
  1362. else if(This->lpdib) {
  1363. StretchDIBits(hdc,
  1364. 0,0,This->lpdibinfo->biWidth,This->lpdibinfo->biHeight,
  1365. 0,0,This->lpdibinfo->biWidth,This->lpdibinfo->biHeight,
  1366. &((BYTE*)(This->lpdib))[sizeof(BITMAPINFOHEADER)],
  1367. (LPBITMAPINFO)This->lpdib,DIB_RGB_COLORS,SRCCOPY);
  1368. }
  1369. }
  1370. EndPaint( hWnd, &paintStruct );
  1371. }
  1372. return 0;
  1373. case WM_TIMER:
  1374. switch(wParam) {
  1375. case 1: // the main animation timer
  1376. KillTimer(hWnd,1);
  1377. This->timer_set=0;
  1378. #ifdef MNGPLG_TRACE
  1379. fprintf(tracefile,"WM_TIMER display_resume bytesloaded=%d\n",This->bytesloaded);
  1380. #endif
  1381. if(This->mng) {
  1382. if(!This->needresume) {
  1383. handle_read_error(This, mng_display_resume(This->mng) );
  1384. }
  1385. }
  1386. return 0;
  1387. case 2: // timer for polling mouse position
  1388. {
  1389. RECT rc;
  1390. POINT pt;
  1391. POINTS pos;
  1392. GetWindowRect(hWnd,&rc);
  1393. GetCursorPos(&pt);
  1394. if(!PtInRect(&rc,pt)) {
  1395. KillTimer(hWnd,2);
  1396. pos.x=0; pos.y=0;
  1397. DynamicMNG_FireEvent(This,3,pos); // 3=mouse leave
  1398. This->mouse_over_mng=0;
  1399. }
  1400. }
  1401. return 0;
  1402. }
  1403. break;
  1404. }
  1405. /* Forward unprocessed messages on to their original destination
  1406. * (the window proc we replaced) */
  1407. return This->fDefaultWindowProc(hWnd, Msg, wParam, lParam);
  1408. }
  1409. static LRESULT CALLBACK DlgProcProp(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  1410. {
  1411. char buf[4096],buf2[1024];
  1412. switch(Msg) {
  1413. case WM_INITDIALOG:
  1414. {
  1415. DWORD tabs[1];
  1416. PluginInstance *This=(PluginInstance*)lParam;
  1417. tabs[0]= 60;
  1418. SendDlgItemMessage(hWnd,IDC_IMGINFO,EM_SETTABSTOPS,(WPARAM)1,(LPARAM)tabs);
  1419. wsprintf(buf,"URL:\t%s\r\n",This->url);
  1420. if(This->lpdib) {
  1421. wsprintf(buf2,"Dimensions:\t%d x %d\r\n",This->lpdibinfo->biWidth,
  1422. This->lpdibinfo->biHeight);
  1423. lstrcat(buf,buf2);
  1424. }
  1425. if(This->lpdib && This->fMode==NP_EMBED) {
  1426. wsprintf(buf2,"Window:\t%d x %d\r\n",This->windowwidth,
  1427. This->windowheight);
  1428. lstrcat(buf,buf2);
  1429. }
  1430. if(This->filesize) {
  1431. wsprintf(buf2,"File size:\t%u bytes\r\n",This->filesize);
  1432. lstrcat(buf,buf2);
  1433. }
  1434. #ifdef _DEBUG
  1435. if(This->mngdata && This->lpdib && This->bytesalloc && This->dibsize) {
  1436. // note this doesn't include memory used by libmng
  1437. wsprintf(buf2,"Memory used:\t%u bytes\r\n",
  1438. This->bytesalloc + This->dibsize);
  1439. lstrcat(buf,buf2);
  1440. }
  1441. #endif
  1442. if(This->islink) {
  1443. wsprintf(buf2,"Link to:\t%s\r\n",This->linkurl);
  1444. lstrcat(buf,buf2);
  1445. if(strcmp(This->linktarget,"_self")) {
  1446. wsprintf(buf2,"Link target:\t%s\r\n",This->linktarget);
  1447. lstrcat(buf,buf2);
  1448. }
  1449. }
  1450. if(This->loadstate >= STATE_VALIDFRAME) {
  1451. wsprintf(buf2,"Signature:\t%s\r\n",get_imagetype_name(mng_get_sigtype(This->mng)));
  1452. lstrcat(buf,buf2);
  1453. wsprintf(buf2,"Image type:\t%s\r\n",get_imagetype_name(mng_get_imagetype(This->mng)));
  1454. lstrcat(buf,buf2);
  1455. wsprintf(buf2,"Simplicity:\t0x%08x\r\n",mng_get_simplicity(This->mng));
  1456. lstrcat(buf,buf2);
  1457. wsprintf(buf2,"Frame count:\t%u\r\n",mng_get_framecount(This->mng));
  1458. lstrcat(buf,buf2);
  1459. wsprintf(buf2,"Layer count:\t%u\r\n",mng_get_layercount(This->mng));
  1460. lstrcat(buf,buf2);
  1461. wsprintf(buf2,"Play time:\t%u\r\n",mng_get_playtime(This->mng));
  1462. lstrcat(buf,buf2);
  1463. }
  1464. SetDlgItemText(hWnd,IDC_IMGINFO,buf);
  1465. if(This->textdata)
  1466. SetDlgItemText(hWnd,IDC_MNGTEXT,This->textdata);
  1467. }
  1468. return(TRUE);
  1469. case WM_CLOSE:
  1470. EndDialog(hWnd,0);
  1471. return(TRUE);
  1472. case WM_COMMAND:
  1473. switch(wParam) {
  1474. case IDOK:
  1475. case IDCANCEL:
  1476. EndDialog(hWnd,0);
  1477. return(TRUE);
  1478. }
  1479. }
  1480. return(FALSE);
  1481. }
  1482. static LRESULT CALLBACK DlgProcAbout(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  1483. {
  1484. char buf[4096],buf2[1024],buf3[300];
  1485. switch(Msg) {
  1486. case WM_INITDIALOG:
  1487. {
  1488. //DWORD tabs[1];
  1489. PluginInstance *This=(PluginInstance*)lParam;
  1490. //tabs[0]= 60;
  1491. //SendDlgItemMessage(hWnd,IDC_IMGINFO,EM_SETTABSTOPS,(WPARAM)1,(LPARAM)tabs);
  1492. wsprintf(buf,"MNGPLG Plug-in, Version %s\r\n%s"
  1493. #ifdef _DEBUG
  1494. " DEBUG BUILD"
  1495. #endif
  1496. "\r\nCopyright (C) 2000-2002 by Jason Summers\r\n\r\n",MNGPLGVERS,__DATE__);
  1497. wsprintf(buf2,"Based on libmng by Gerard Juyn.\r\n");
  1498. lstrcat(buf,buf2);
  1499. wsprintf(buf2,"libmng version: %s\r\n\r\n",mng_version_text());
  1500. lstrcat(buf,buf2);
  1501. wsprintf(buf2,"Uses the zlib compression library.\r\n");
  1502. lstrcat(buf,buf2);
  1503. wsprintf(buf2,"zlib version: %s\r\n\r\n",zlibVersion());
  1504. lstrcat(buf,buf2);
  1505. wsprintf(buf2,"This software is based in part on the work of the "
  1506. "Independent JPEG Group.\r\n");
  1507. lstrcat(buf,buf2);
  1508. // This really only gives the version of the libjpeg header used when
  1509. // compiling this plugin, but I don't know how to query libjpeg for its
  1510. // version.
  1511. wsprintf(buf2,"IJG JPEG library version: %s\r\n%s\r\n\r\n",JVERSION,JCOPYRIGHT);
  1512. lstrcat(buf,buf2);
  1513. #ifdef MNGPLG_CMS
  1514. wsprintf(buf2,"Uses the lcms color management library by Martí Maria. "
  1515. "lcms is distributed under the terms of the GNU LESSER GENERAL PUBLIC LICENSE. "
  1516. "See the file COPYING-LCMS.\r\n\r\n");
  1517. lstrcat(buf,buf2);
  1518. #endif
  1519. if(GetModuleFileName(g_hInst,buf3,260)) {
  1520. wsprintf(buf2,"MNGPLG location: %s\r\n",buf3);
  1521. lstrcat(buf,buf2);
  1522. }
  1523. SetDlgItemText(hWnd,IDC_PRGINFO,buf);
  1524. }
  1525. return(TRUE);
  1526. case WM_CLOSE:
  1527. EndDialog(hWnd,0);
  1528. return(TRUE);
  1529. case WM_COMMAND:
  1530. switch(wParam) {
  1531. case IDOK:
  1532. case IDCANCEL:
  1533. EndDialog(hWnd,0);
  1534. return(TRUE);
  1535. }
  1536. }
  1537. return(FALSE);
  1538. }
  1539. /////////////////////
  1540. ///////////////////// low-level plug-in NPAPI functions
  1541. static JRIGlobalRef Private_GetJavaClass(void)
  1542. {
  1543. return NULL;
  1544. }
  1545. NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pFuncs)
  1546. {
  1547. if(!pFuncs) return NPERR_INVALID_FUNCTABLE_ERROR;
  1548. pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
  1549. pFuncs->newp = NPP_New;
  1550. pFuncs->destroy = NPP_Destroy;
  1551. pFuncs->setwindow = NPP_SetWindow;
  1552. pFuncs->newstream = NPP_NewStream;
  1553. pFuncs->destroystream = NPP_DestroyStream;
  1554. pFuncs->asfile = NPP_StreamAsFile;
  1555. pFuncs->writeready = NPP_WriteReady;
  1556. pFuncs->write = NPP_Write;
  1557. pFuncs->print = NPP_Print;
  1558. pFuncs->event = NULL;
  1559. g_pluginFuncs = pFuncs;
  1560. return NPERR_NO_ERROR;
  1561. }
  1562. NPError WINAPI NP_Initialize(NPNetscapeFuncs* pFuncs)
  1563. {
  1564. int navMinorVers;
  1565. if(!pFuncs) return NPERR_INVALID_FUNCTABLE_ERROR;
  1566. g_pNavigatorFuncs = pFuncs; // save it for future reference
  1567. if(HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
  1568. return NPERR_INCOMPATIBLE_VERSION_ERROR;
  1569. navMinorVers = g_pNavigatorFuncs->version & 0xFF;
  1570. if(navMinorVers>=NPVERS_HAS_NOTIFICATION)
  1571. g_pluginFuncs->urlnotify = NPP_URLNotify;
  1572. if( navMinorVers>=NPVERS_HAS_LIVECONNECT)
  1573. g_pluginFuncs->javaClass = Private_GetJavaClass();
  1574. return NPP_Initialize();
  1575. }
  1576. NPError WINAPI NP_Shutdown()
  1577. {
  1578. NPP_Shutdown();
  1579. g_pNavigatorFuncs = NULL;
  1580. return NPERR_NO_ERROR;
  1581. }