1
/* $Xorg: Main.c,v 1.5 2001/02/09 02:05:57 xorgcvs Exp $ */
4
Copyright 1996, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included
13
in all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
17
ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
18
SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL-
19
ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
Except as contained in this notice, the name of The Open Group shall
24
not be used in advertising or otherwise to promote the sale, use or
25
other dealings in this Software without prior written authorization from
29
/* $XFree86: xc/programs/xrx/plugin/Main.c,v 1.8 2001/12/14 20:02:17 dawes Exp $ */
32
* RX plug-in module based on the UnixTemplate file provided by Netcape.
35
/* -*- Mode: C; tab-width: 4; -*- */
36
/******************************************************************************
37
* Copyright 1996 Netscape Communications. All rights reserved.
38
******************************************************************************/
42
* Netscape Client Plugin API
43
* - Function that need to be implemented by plugin developers
45
* This file defines a "Template" plugin that plugin developers can use
46
* as the basis for a real plugin. This shell just provides empty
47
* implementations of all functions that the plugin can implement
48
* that will be called by Netscape (the NPP_xxx methods defined in
51
* dp Suresh <dp@netscape.com>
58
#include "X11/StringDefs.h"
61
/***********************************************************************
62
* Utility functions to deal with list of arguments
63
***********************************************************************/
65
/* Free list of arguments */
67
FreeArgs(char* argn[], char* argv[], int argc)
71
for (i = 0; i < argc; i++) {
80
/* Copy list 2 to list 1 */
82
CopyArgs(char** argn1[], char** argv1[], int16* argc1,
83
char* argn2[], char* argv2[], int16 argc2)
88
argn = (char **)NPN_MemAlloc(sizeof(char *) * argc2);
90
return NPERR_OUT_OF_MEMORY_ERROR;
91
argv = (char **)NPN_MemAlloc(sizeof(char *) * argc2);
94
return NPERR_OUT_OF_MEMORY_ERROR;
96
memset(argn, 0, sizeof(char *) * argc2);
97
memset(argv, 0, sizeof(char *) * argc2);
98
for (i = 0; i < argc2; i++) {
100
name = (char *)NPN_MemAlloc(strlen(argn2[i]) + 1);
102
FreeArgs(argn, argv, i - 1);
103
return NPERR_OUT_OF_MEMORY_ERROR;
105
strcpy(name, argn2[i]);
106
value = (char *)NPN_MemAlloc(strlen(argv2[i]) + 1);
109
FreeArgs(argn, argv, i - 1);
110
return NPERR_OUT_OF_MEMORY_ERROR;
112
strcpy(value, argv2[i]);
120
return NPERR_NO_ERROR;
125
NPP_GetMIMEDescription(void)
127
return(PLUGIN_MIME_DESCRIPTION);
131
NPP_GetValue(void *future, NPPVariable variable, void *value)
133
NPError err = NPERR_NO_ERROR;
136
case NPPVpluginNameString:
137
*((char **)value) = PLUGIN_NAME;
139
case NPPVpluginDescriptionString:
140
*((char **)value) = PLUGIN_DESCRIPTION;
143
err = NPERR_GENERIC_ERROR;
155
NPP_New(NPMIMEType pluginType,
163
PluginInstance* This;
165
if (instance == NULL)
166
return NPERR_INVALID_INSTANCE_ERROR;
168
instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
170
This = (PluginInstance*) instance->pdata;
173
return NPERR_OUT_OF_MEMORY_ERROR;
175
This->instance = instance;
176
if (argc != 0) { /* copy the arguments list */
177
if (CopyArgs(&This->argn, &This->argv, &This->argc,
178
argn, argv, argc) == NPERR_OUT_OF_MEMORY_ERROR) {
180
return NPERR_OUT_OF_MEMORY_ERROR;
184
This->argn = This->argv = NULL;
186
This->parse_reply = 0;
188
This->dont_reparent = RxUndef;
189
This->state = LOADING;
190
This->status_widget = NULL;
191
This->plugin_widget = NULL;
194
return NPERR_NO_ERROR;
199
NPP_Destroy(NPP instance, NPSavedData** save)
201
PluginInstance* This;
203
if (instance == NULL)
204
return NPERR_INVALID_INSTANCE_ERROR;
206
This = (PluginInstance*) instance->pdata;
208
/* PLUGIN DEVELOPERS:
209
* If desired, call NP_MemAlloc to create a
210
* NPSavedDate structure containing any state information
211
* that you want restored if this plugin instance is later
218
FreeArgs(This->argn, This->argv, This->argc);
219
if (This->query != NULL)
220
NPN_MemFree(This->query);
221
NPN_MemFree(instance->pdata);
222
instance->pdata = NULL;
225
return NPERR_NO_ERROR;
229
/* private buffer structure */
236
NPP_NewStream(NPP instance,
242
PluginInstance* This;
243
RxStreamBuf *streambuf;
245
if (instance == NULL)
246
return NPERR_INVALID_INSTANCE_ERROR;
248
This = (PluginInstance*) instance->pdata;
250
if (This->parse_reply != 0)
251
return NPERR_NO_ERROR;
253
/* malloc structure to store RX document */
254
streambuf = (RxStreamBuf *) NPN_MemAlloc(sizeof(RxStreamBuf));
255
if (streambuf == NULL)
256
return NPERR_OUT_OF_MEMORY_ERROR;
258
streambuf->buf = NULL;
260
stream->pdata = (void *) streambuf;
262
return NPERR_NO_ERROR;
266
/* PLUGIN DEVELOPERS:
267
* These next 2 functions are directly relevant in a plug-in which
268
* handles the data in a streaming manner. If you want zero bytes
269
* because no buffer space is YET available, return 0. As long as
270
* the stream has not been written to the plugin, Navigator will
271
* continue trying to send bytes. If the plugin doesn't want them,
272
* just return some large number from NPP_WriteReady(), and
273
* ignore them in NPP_Write(). For a NP_ASFILE stream, they are
274
* still called but can safely be ignored using this strategy.
277
int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
278
* mode so we can take any size stream in our
279
* write call (since we ignore it) */
282
NPP_WriteReady(NPP instance, NPStream *stream)
284
PluginInstance* This;
285
if (instance != NULL)
286
This = (PluginInstance*) instance->pdata;
288
return STREAMBUFSIZE;
292
NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buf)
294
PluginInstance* This;
296
if (instance == NULL)
299
This = (PluginInstance*) instance->pdata;
301
if (This->parse_reply == 0) {
302
/* copy stream buffer to private storage, concatenating if necessary:
303
* since Netscape doesn't provide an NPN_MemRealloc we must do
304
* a new malloc, copy, and free :-(
306
RxStreamBuf *streambuf = (RxStreamBuf *) stream->pdata;
307
uint32 size = streambuf->size;
310
/* if first chunk add 1 for null terminating character */
315
cbuf = (char *) NPN_MemAlloc(size);
318
if (streambuf->size != 0) {
319
memcpy(cbuf, streambuf->buf, streambuf->size - 1);
320
memcpy(cbuf + streambuf->size - 1, ((char *)buf), len);
321
/* free old storage */
322
NPN_MemFree((void *) streambuf->buf);
324
memcpy(cbuf, ((char *)buf), len);
325
cbuf[size - 1] = '\0';
326
/* store new buffer */
327
streambuf->buf = cbuf;
328
streambuf->size = size;
330
fprintf(stderr, "write %s:\n", PLUGIN_NAME);
331
fwrite(buf, len, 1, stderr);
332
fprintf(stderr, "\n");
336
if (This->parse_reply == 1) {
337
/* look for status line */
338
char *ptr = strchr(buf, '\n');
339
if (ptr != NULL && isdigit(((char *)buf)[0])) {
340
This->status = (short) atoi((char *)buf);
341
/* skip status line */
342
l -= ptr - (char *)buf + 1;
344
if (This->status != 0) {
346
"%s: Application failed to start properly\n",
350
This->parse_reply = 2;
352
/* simply prints out whatever we get, and let netscape display it
354
fwrite(buf, l, 1, stderr);
357
return len; /* The number of bytes accepted */
361
StartApplication(PluginInstance* This)
365
#ifndef NO_STARTING_STATE
366
RxpSetStatusWidget(This, STARTING);
368
RxpSetStatusWidget(This, RUNNING);
371
/* perform GET request
372
* throwing away the response.
374
err = NPN_GetURL(This->instance, This->query, NULL);
375
This->parse_reply = 1; /* we want to print out the answer */
379
StartCB(Widget widget, XtPointer client_data, XtPointer call_data)
381
PluginInstance* This = (PluginInstance*) client_data;
383
XtUnmapWidget(widget);
385
XtDestroyWidget(widget);
386
StartApplication(This);
389
#if defined(linux) || (defined(sun) && !defined(SVR4))
390
/* deficient linux linker semantics */
391
static WidgetClass xmLabelGadgetClass;
392
static WidgetClass xmPushButtonGadgetClass;
394
extern WidgetClass xmLabelGadgetClass;
395
extern WidgetClass xmPushButtonGadgetClass;
399
RxpSetStatusWidget(PluginInstance* This, PluginState state)
405
XrmValue return_value;
407
if (This->status_widget) {
408
XtDestroyWidget(This->status_widget);
409
This->status_widget = NULL;
411
if (This->plugin_widget == NULL)
414
db = XtDatabase (XtDisplay (This->plugin_widget));
416
if (!XrmGetResource (db, "RxPlugin_BeenHere", "RxPlugin_BeenHere",
417
&return_type, &return_value)) {
419
XrmPutStringResource (&db, "*Rx_Loading.labelString", "Loading...");
420
XrmPutStringResource (&db, "*Rx_Starting.labelString", "Starting...");
421
XrmPutStringResource (&db, "*Rx_Start.labelString", "Start");
422
XrmPutStringResource (&db, "RxPlugin_BeenHere", "YES");
424
#if defined(linux) || (defined(sun) && !defined(SVR4))
426
lame loader semantics mean we have to go fishing around to
427
come up with widget class records so we can create some widgets.
429
Names of widgets changed in 4.x, so look for those names too
432
If Microsoft ever does IE for Linux we'll have to figure out
435
if (xmLabelGadgetClass == NULL) {
438
w = XtNameToWidget (This->toplevel_widget, "*topLeftArea.urlLabel");
440
w = XtNameToWidget (This->toplevel_widget, "*urlBar.urlLocationLabel");
441
xmLabelGadgetClass = XtClass (w);
442
w = XtNameToWidget (This->toplevel_widget, "*toolBar.abort");
444
w = XtNameToWidget (This->toplevel_widget, "*PopupMenu.openCustomUrl");
445
xmPushButtonGadgetClass = XtClass (w);
450
XtSetArg(args[n], "shadowThickness", 1); n++;
451
XtSetArg(args[n], XtNwidth, This->width); n++;
452
XtSetArg(args[n], XtNheight, This->height); n++;
453
if (state == LOADING) {
455
This->status_widget =
456
XtCreateManagedWidget("Rx_Loading", xmLabelGadgetClass,
457
This->plugin_widget, args, n);
458
#ifndef NO_STARTING_STATE
459
} else if (state == STARTING) {
461
This->status_widget =
462
XtCreateManagedWidget("Rx_Starting", xmLabelGadgetClass,
463
This->plugin_widget, args, n);
465
} else if (state == WAITING) {
466
/* create a push button */
467
This->status_widget =
468
XtCreateManagedWidget("Rx_Start", xmPushButtonGadgetClass,
469
This->plugin_widget, args, n);
470
XtAddCallback(This->status_widget, "activateCallback", StartCB, This);
471
} else if (state == RUNNING) {
472
/* nothing else to be done */
479
NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
481
PluginInstance* This;
482
RxStreamBuf *streambuf = (RxStreamBuf *) stream->pdata;
483
char **rx_argn, **rx_argv;
486
RxReturnParams return_params;
487
NPError status = NPERR_NO_ERROR;
489
if (instance == NULL)
490
return NPERR_INVALID_INSTANCE_ERROR;
492
This = (PluginInstance*) instance->pdata;
494
if (This->parse_reply != 0) {
496
if (This->status != 0) /* if error occured change widget status */
497
RxpSetStatusWidget(This, WAITING);
501
memset(¶ms, 0, sizeof(RxParams));
502
memset(&return_params, 0, sizeof(RxReturnParams));
505
if (reason != NPRES_DONE) {
506
status = NPERR_GENERIC_ERROR;
510
/* read params from stream */
511
if (RxReadParams(streambuf->buf, &rx_argn, &rx_argv, &rx_argc) != 0) {
512
fprintf(stderr, "%s: invalid file %s\n", PLUGIN_NAME, stream->url);
513
status = NPERR_GENERIC_ERROR;
517
RxInitializeParams(¶ms);
519
/* parse RX params */
520
if (RxParseParams(rx_argn, rx_argv, rx_argc, ¶ms, 0) != 0) {
521
fprintf(stderr, "%s: invalid RX params\n", PLUGIN_NAME);
522
status = NPERR_GENERIC_ERROR;
526
/* parse HTML params */
527
if (RxParseParams(This->argn, This->argv, This->argc, ¶ms, 0) != 0) {
528
fprintf(stderr, "%s: invalid HTML params\n", PLUGIN_NAME);
529
status = NPERR_GENERIC_ERROR;
533
/* set up return parameters */
534
if (RxpProcessParams(This, ¶ms, &return_params) != 0) {
535
fprintf(stderr, "%s: failed to process params\n", PLUGIN_NAME);
536
status = NPERR_GENERIC_ERROR;
541
This->query = RxBuildRequest(&return_params);
542
if (This->query == NULL) {
543
fprintf(stderr, "%s: failed to make query\n", PLUGIN_NAME);
544
status = NPERR_GENERIC_ERROR;
548
if (params.auto_start != RxFalse) /* default is auto start */
549
StartApplication(This);
551
RxpSetStatusWidget(This, WAITING);
554
/* free all forms of params */
555
FreeArgs(rx_argn, rx_argv, rx_argc);
556
FreeArgs(This->argn, This->argv, This->argc);
558
RxFreeParams(¶ms);
559
RxFreeReturnParams(&return_params);
560
/* free private storage */
561
if (streambuf->buf != NULL)
562
NPN_MemFree(streambuf->buf);
563
NPN_MemFree(stream->pdata);
569
NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
572
PluginInstance* This;
573
if (instance != NULL)
574
This = (PluginInstance*) instance->pdata;
580
NPP_Print(NPP instance, NPPrint* printInfo)
582
if(printInfo == NULL)
585
if (instance != NULL) {
587
PluginInstance* This = (PluginInstance*) instance->pdata;
590
if (printInfo->mode == NP_FULL) {
593
* If your plugin would like to take over
594
* printing completely when it is in full-screen mode,
595
* set printInfo->pluginPrinted to TRUE and print your
596
* plugin as you see fit. If your plugin wants Netscape
597
* to handle printing in this case, set
598
* printInfo->pluginPrinted to FALSE (the default) and
599
* do nothing. If you do want to handle printing
600
* yourself, printOne is true if the print button
601
* (as opposed to the print menu) was clicked.
602
* On the Macintosh, platformPrint is a THPrint; on
603
* Windows, platformPrint is a structure
604
* (defined in npapi.h) containing the printer name, port,
609
void* platformPrint =
610
printInfo->print.fullPrint.platformPrint;
612
printInfo->print.fullPrint.printOne;
616
printInfo->print.fullPrint.pluginPrinted = FALSE;
619
else { /* If not fullscreen, we must be embedded */
622
* If your plugin is embedded, or is full-screen
623
* but you returned false in pluginPrinted above, NPP_Print
624
* will be called with mode == NP_EMBED. The NPWindow
625
* in the printInfo gives the location and dimensions of
626
* the embedded plugin on the printed page. On the
627
* Macintosh, platformPrint is the printer port; on
628
* Windows, platformPrint is the handle to the printing
632
NPWindow* printWindow =
633
&(printInfo->print.embedPrint.window);
634
void* platformPrint =
635
printInfo->print.embedPrint.platformPrint;