home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / htmldlgs / htmldlgs.c next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  47.4 KB  |  1,945 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*
  19.  * Cross platform html dialogs
  20.  *
  21.  *
  22.  * $Id: htmldlgs.c,v 3.1 1998/03/28 03:29:14 ltabb Exp $
  23.  */
  24.  
  25. #include "xp.h"
  26. #include "fe_proto.h"
  27. #include "seccomon.h"
  28. #include "net.h"
  29. #include "htmldlgs.h"
  30. #include "xpgetstr.h"
  31. #include "shist.h"
  32. #include "prlog.h"
  33. #include "libmocha.h"
  34. #include "prclist.h"
  35.  
  36. extern int XP_SEC_CANCEL;
  37. extern int XP_SEC_OK;
  38. extern int XP_SEC_CONTINUE;
  39. extern int XP_SEC_NEXT;
  40. extern int XP_SEC_BACK;
  41. extern int XP_SEC_FINISHED;
  42. extern int XP_SEC_MOREINFO;
  43. extern int XP_SEC_CONFIG;
  44. extern int XP_SEC_SHOWCERT;
  45. extern int XP_SEC_SHOWORDER;
  46. extern int XP_SEC_SHOWDOCINFO;
  47. extern int XP_SEC_NEXT_KLUDGE;
  48. extern int XP_SEC_BACK_KLUDGE;
  49. extern int XP_SEC_RENEW;
  50. extern int XP_SEC_NEW;
  51. extern int XP_SEC_RELOAD;
  52. extern int XP_SEC_DELETE;
  53. extern int XP_SEC_EDIT;
  54. extern int XP_SEC_LOGIN;
  55. extern int XP_SEC_LOGOUT;
  56. extern int XP_SEC_SETPASSWORD;
  57. extern int XP_SEC_SAVEAS;
  58. extern int XP_SEC_FETCH;
  59.  
  60. extern int XP_DIALOG_CANCEL_BUTTON_STRINGS;
  61. extern int XP_DIALOG_CANCEL_CONTINUE_BUTTON_STRINGS;
  62. extern int XP_DIALOG_CANCEL_OK_BUTTON_STRINGS;
  63. extern int XP_DIALOG_CANCEL_OK_MOREINFO_BUTTON_STRINGS;
  64. extern int XP_DIALOG_FETCH_CANCEL_BUTTON_STRINGS;
  65. extern int XP_DIALOG_CONTINUE_BUTTON_STRINGS;
  66. extern int XP_DIALOG_FOOTER_STRINGS;
  67. extern int XP_DIALOG_HEADER_STRINGS;
  68. extern int XP_DIALOG_MIDDLE_STRINGS;
  69. extern int XP_DIALOG_NULL_STRINGS;
  70. extern int XP_DIALOG_OK_BUTTON_STRINGS;
  71. extern int XP_EMPTY_STRINGS;
  72. extern int XP_PANEL_FIRST_BUTTON_STRINGS;
  73. extern int XP_PANEL_FOOTER_STRINGS;
  74. extern int XP_PANEL_HEADER_STRINGS;
  75. extern int XP_PANEL_LAST_BUTTON_STRINGS;
  76. extern int XP_PANEL_MIDDLE_BUTTON_STRINGS;
  77. extern int XP_PANEL_ONLY_BUTTON_STRINGS;
  78. extern int XP_ALERT_TITLE_STRING;
  79. extern int XP_DIALOG_JS_HEADER_STRINGS;
  80. extern int XP_DIALOG_JS_HEADER_STRINGS_WITH_UTF8_CHARSET;
  81. extern int XP_DIALOG_JS_MIDDLE_STRINGS;
  82. extern int XP_DIALOG_JS_FOOTER_STRINGS;
  83. extern int XP_BANNER_FONTFACE_INFO_STRING;
  84. extern int XP_DIALOG_STYLEINFO_STRING;
  85.  
  86. typedef struct {
  87.     PRCList link;
  88.     char *data;
  89.     unsigned int len;
  90. } bufferNode;
  91.  
  92. typedef struct _htmlDialogStream {
  93.     PRCList queuedBuffers;
  94.     PRArenaPool *arena;
  95.     NET_StreamClass *stream;
  96.     URL_Struct *url;
  97.     PRBool buffering;
  98.     char *curbuf;
  99.     unsigned int curlen;
  100. } HTMLDialogStream;
  101.  
  102. typedef struct {
  103.     void *window;
  104.     void (* deleteWinCallback)(void *arg);
  105.     void *arg;
  106.     PRArenaPool *freeArena;
  107. } deleteWindowCBArg;
  108.  
  109. static void
  110. deleteWindow(void *closure)
  111. {
  112.     deleteWindowCBArg *state;
  113.     
  114.     state = (deleteWindowCBArg *)closure;
  115.     
  116.     FE_DestroyWindow((MWContext *)state->window);
  117.  
  118.     if ( state->deleteWinCallback ) {
  119.     (* state->deleteWinCallback)(state->arg);
  120.     }
  121.  
  122.     if ( state->freeArena != NULL ) {
  123.     PORT_FreeArena(state->freeArena, PR_FALSE);
  124.     }
  125.     
  126.     PORT_Free(state);
  127.     
  128.     return;
  129. }
  130.  
  131. static SECStatus
  132. writeOrBuffer(HTMLDialogStream *stream)
  133. {
  134.     unsigned int cnt;
  135.     char *tmpdest;
  136.     bufferNode *node;
  137.     int ret;
  138.     
  139.     if ( ! stream->buffering ) {
  140.     cnt = (*(stream->stream)->is_write_ready)
  141.         (stream->stream);
  142.     /* if stream is clogged, then start buffering */
  143.     if ( cnt < stream->curlen ) {
  144.         /* we need to copy the current contents of the reusable
  145.          * buffer to a persistent buffer allocated from the
  146.          * arena, then free the persistent buffer
  147.          */
  148.         tmpdest = (char *)PORT_ArenaAlloc(stream->arena, stream->curlen);
  149.         if ( tmpdest == NULL ) {
  150.         goto loser;
  151.         }
  152.  
  153.         PORT_Memcpy(tmpdest, stream->curbuf, stream->curlen);
  154.         PORT_Free(stream->curbuf);
  155.         stream->curbuf = tmpdest;
  156.         stream->buffering = PR_TRUE;
  157.     }
  158.     }
  159.  
  160.     if ( stream->buffering ) {
  161.     node = PORT_ArenaAlloc(stream->arena, sizeof(bufferNode));
  162.     if ( node == NULL ) {
  163.         goto loser;
  164.     }
  165.     
  166.     PR_APPEND_LINK(&node->link, &stream->queuedBuffers);
  167.  
  168.     node->data = stream->curbuf;
  169.     node->len = stream->curlen;
  170.     } else {
  171.     ret = (*(stream->stream)->put_block)
  172.         (stream->stream, stream->curbuf, stream->curlen);
  173.     if ( ret < 0 ) {
  174.         goto loser;
  175.     }
  176.     }
  177.  
  178.     return(SECSuccess);
  179. loser:
  180.     return(SECFailure);
  181. }
  182.  
  183. static SECStatus
  184. putStringToStream(HTMLDialogStream *stream, char *string, PRBool quote)
  185. {
  186.     SECStatus rv;
  187.     char *tmpptr;
  188.     char *destptr;
  189.     int curcount;
  190.     unsigned int maxsize;
  191.  
  192.     if (*string == 0) {
  193.     return(SECSuccess);
  194.     }
  195.  
  196.     if ( stream->buffering ) {
  197.     /* pick a size that is convenient based on the current behaviour
  198.      * of the html parser
  199.      */
  200.     maxsize = 2000; /* XXX - we know what the parser does here!! */
  201.     stream->curbuf = destptr = (char *)PORT_ArenaAlloc(stream->arena,
  202.                                maxsize);
  203.     } else {
  204.     maxsize = (*(stream->stream)->is_write_ready)
  205.         (stream->stream);
  206.     
  207.     if ( maxsize == 0 ) {
  208.         /* we are switching to buffering now */
  209.         maxsize = 2000;
  210.         stream->curbuf = destptr = (char *)PORT_ArenaAlloc(stream->arena,
  211.                                    maxsize);
  212.         stream->buffering = PR_TRUE;
  213.     } else {
  214.         stream->curbuf = destptr = (char *)PORT_Alloc( maxsize );
  215.     }
  216.     }
  217.  
  218.     if ( stream->curbuf == NULL ) {
  219.     return(SECFailure);
  220.     }
  221.  
  222.     curcount = 0;
  223.     tmpptr = string;
  224.  
  225.     if ( quote ) {
  226.     while ( *tmpptr ) {
  227.         if ( *tmpptr == '\'' ) {
  228.         *destptr = '\\';
  229.         destptr++;
  230.         *destptr = *tmpptr;
  231.         destptr++;
  232.         curcount += 2;
  233.         } else if ( *tmpptr == '\\' ) {
  234.         *destptr = '\\';
  235.         destptr++;
  236.         *destptr = '\\';
  237.         destptr++;
  238.         curcount += 2;
  239.         } else if ( *tmpptr == '\n' ) {
  240.         *destptr = '\\';
  241.         destptr++;
  242.         *destptr = 'n';
  243.         destptr++;
  244.         curcount += 2;
  245.         } else if ( *tmpptr == '\r' ) {
  246.         *destptr = '\\';
  247.         destptr++;
  248.         *destptr = 'r';
  249.         destptr++;
  250.         curcount += 2;
  251.         } else if ( *tmpptr == '/' ) {
  252.         *destptr = '\\';
  253.         destptr++;
  254.         *destptr = '/';
  255.         destptr++;
  256.         curcount += 2;
  257.         } else {
  258.         *destptr = *tmpptr;
  259.         destptr++;
  260.         curcount++;
  261.         }
  262.  
  263.         tmpptr++;
  264.         if ( curcount >= ( maxsize - 1 ) ) {
  265.         stream->curlen = curcount;
  266.         rv = writeOrBuffer(stream);
  267.         if ( rv != SECSuccess ) {
  268.             goto loser;
  269.         }
  270.         
  271.         if ( stream->buffering && ( *tmpptr != '\0' ) ) {
  272.             maxsize = 2000; /*XXX-we know what the parser does here!!*/
  273.             stream->curbuf = destptr =
  274.             (char *)PORT_ArenaAlloc(stream->arena, maxsize);
  275.             if ( stream->curbuf == NULL ) {
  276.             goto loser;
  277.             }
  278.         } else {
  279.             destptr = stream->curbuf;
  280.         }
  281.         curcount = 0;
  282.         }
  283.     }
  284.     } else {
  285.     while ( *tmpptr ) {
  286.         *destptr = *tmpptr;
  287.         destptr++;
  288.         curcount++;
  289.         tmpptr++;
  290.  
  291.         if ( curcount >= ( maxsize - 1 ) ) {
  292.         stream->curlen = curcount;
  293.         rv = writeOrBuffer(stream);
  294.         if ( rv != SECSuccess ) {
  295.             goto loser;
  296.         }
  297.         
  298.         if ( stream->buffering && ( *tmpptr != '\0') ) {
  299.             maxsize = 2000; /*XXX-we know what the parser does here!!*/
  300.             stream->curbuf = destptr =
  301.             (char *)PORT_ArenaAlloc(stream->arena, maxsize);
  302.             if ( stream->curbuf == NULL ) {
  303.             goto loser;
  304.             }
  305.         } else {
  306.             destptr = stream->curbuf;
  307.         }
  308.         curcount = 0;
  309.         }
  310.     }
  311.     }
  312.  
  313.     if ( curcount > 0 ) {
  314.     stream->curlen = curcount;
  315.     rv = writeOrBuffer(stream);
  316.     if ( rv != SECSuccess ) {
  317.         goto loser;
  318.     }
  319.     }
  320.  
  321.     rv = SECSuccess;
  322.     goto done;
  323.     
  324. loser:
  325.     rv = SECFailure;
  326. done:
  327.     if ( ( !stream->buffering ) && ( stream->curbuf != NULL ) ) {
  328.     PORT_Free(stream->curbuf);
  329.     }
  330.  
  331.     return(rv);
  332. }
  333.  
  334. SECStatus
  335. XP_PutDialogStringsToStream(HTMLDialogStream *stream, XPDialogStrings *strs,
  336.                 PRBool quote)
  337. {
  338.     SECStatus rv;
  339.     char *src, *token, *junk;
  340.     int argnum;
  341.     void *proto_win = stream->stream->window_id;    
  342.     src = strs->contents;
  343.     
  344.     while ((token = PORT_Strchr(src, '%'))) {
  345.     *token = 0;
  346.     rv = putStringToStream(stream, src, quote);
  347.     if (rv) {
  348.         return(SECFailure);
  349.     }
  350.     *token = '%';        /* non-destructive... */
  351.     token++;        /* now points to start of token */
  352.     src = PORT_Strchr(token, '%');
  353.     *src = 0;
  354.     
  355.     argnum = (int)XP_STRTOUL(token, &junk, 10);
  356.     if (junk != token) {    /* A number */
  357.         PORT_Assert(argnum <= strs->nargs);
  358.         if (strs->args[argnum]) {
  359.         rv = putStringToStream(stream, strs->args[argnum],
  360.                        quote);
  361.         if (rv) {
  362.              return(SECFailure);
  363.         }
  364.         }
  365.     }
  366.     else if (!PORT_Strcmp(token, "-cont-")) /* continuation */
  367.         /* Do Nothing */;
  368.     else if (*token == 0) {    /* %% -> % */
  369.         rv = putStringToStream(stream, "%", quote);
  370.         if (rv) {
  371.          return(SECFailure);
  372.         }
  373.     }
  374.     else if (!PORT_Strcmp(token, "cancel")) {
  375.         rv = putStringToStream(stream,
  376.                    XP_GetString(XP_SEC_CANCEL),
  377.                    quote);
  378.         if (rv) {
  379.         return(SECFailure);
  380.         }
  381.     }
  382.     else if (!PORT_Strcmp(token, "ok")) {
  383.         rv = putStringToStream(stream,
  384.                    XP_GetString(XP_SEC_OK),
  385.                    quote);
  386.         if (rv) {
  387.         return(SECFailure);
  388.         }
  389.     }
  390.     else if (!PORT_Strcmp(token, "continue")) {
  391.         rv = putStringToStream(stream,
  392.                    XP_GetString(XP_SEC_CONTINUE),
  393.                    quote);
  394.         if (rv) {
  395.         return(SECFailure);
  396.         }
  397.     }
  398.     else if (!PORT_Strcmp(token, "next")) {
  399.         rv = putStringToStream(stream,
  400.                    XP_GetString(XP_SEC_NEXT),
  401.                    quote);
  402.         if (rv) {
  403.         return(SECFailure);
  404.         }
  405.     }
  406.     else if (!PORT_Strcmp(token, "back")) {
  407.         rv = putStringToStream(stream,
  408.                    XP_GetString(XP_SEC_BACK),
  409.                    quote);
  410.         if (rv) {
  411.         return(SECFailure);
  412.         }
  413.     }
  414.     else if (!PORT_Strcmp(token, "finished")) {
  415.         rv = putStringToStream(stream,
  416.                    XP_GetString(XP_SEC_FINISHED),
  417.                    quote);
  418.         if (rv) {
  419.         return(SECFailure);
  420.         }
  421.     }
  422.     else if (!PORT_Strcmp(token, "moreinfo")) {
  423.         rv = putStringToStream(stream,
  424.                    XP_GetString(XP_SEC_MOREINFO),
  425.                    quote);
  426.         if (rv) {
  427.         return(SECFailure);
  428.         }
  429.     }
  430.     else if (!PORT_Strcmp(token, "config")) {
  431.         rv = putStringToStream(stream,
  432.                    XP_GetString(XP_SEC_CONFIG),
  433.                    quote);
  434.         if (rv) {
  435.         return(SECFailure);
  436.         }
  437.     }
  438.     else if (!PORT_Strcmp(token, "showcert")) {
  439.         rv = putStringToStream(stream,
  440.                    XP_GetString(XP_SEC_SHOWCERT),
  441.                    quote);
  442.         if (rv) {
  443.         return(SECFailure);
  444.         }
  445.     }
  446.     else if (!PORT_Strcmp(token, "showorder")) {
  447.         rv = putStringToStream(stream,
  448.                    XP_GetString(XP_SEC_SHOWORDER),
  449.                    quote);
  450.         if (rv) {
  451.         return(SECFailure);
  452.         }
  453.     }
  454.     else if (!PORT_Strcmp(token, "showdocinfo")) {
  455.         rv = putStringToStream(stream,
  456.                    XP_GetString(XP_SEC_SHOWDOCINFO),
  457.                    quote);
  458.         if (rv) {
  459.         return(SECFailure);
  460.         }
  461.     }
  462.     else if (!PORT_Strcmp(token, "renew")) {
  463.         rv = putStringToStream(stream,
  464.                    XP_GetString(XP_SEC_RENEW),
  465.                    quote);
  466.         if (rv) {
  467.         return(SECFailure);
  468.         }
  469.     }
  470.     else if (!PORT_Strcmp(token, "new")) {
  471.         rv = putStringToStream(stream,
  472.                    XP_GetString(XP_SEC_NEW),
  473.                    quote);
  474.         if (rv) {
  475.         return(SECFailure);
  476.         }
  477.     }
  478.     else if (!PORT_Strcmp(token, "reload")) {
  479.         rv = putStringToStream(stream,
  480.                    XP_GetString(XP_SEC_RELOAD),
  481.                    quote);
  482.         if (rv) {
  483.         return(SECFailure);
  484.         }
  485.     }
  486.     else if (!PORT_Strcmp(token, "delete")) {
  487.         rv = putStringToStream(stream,
  488.                    XP_GetString(XP_SEC_DELETE),
  489.                    quote);
  490.         if (rv) {
  491.         return(SECFailure);
  492.         }
  493.     }
  494.     else if (!PORT_Strcmp(token, "edit")) {
  495.         rv = putStringToStream(stream,
  496.                    XP_GetString(XP_SEC_EDIT),
  497.                    quote);
  498.         if (rv) {
  499.         return(SECFailure);
  500.         }
  501.     }
  502.     else if (!PORT_Strcmp(token, "login")) {
  503.         rv = putStringToStream(stream,
  504.                    XP_GetString(XP_SEC_LOGIN),
  505.                    quote);
  506.         if (rv) {
  507.         return(SECFailure);
  508.         }
  509.     }
  510.     else if (!PORT_Strcmp(token, "logout")) {
  511.         rv = putStringToStream(stream,
  512.                    XP_GetString(XP_SEC_LOGOUT),
  513.                    quote);
  514.         if (rv) {
  515.         return(SECFailure);
  516.         }
  517.     }
  518.     else if (!PORT_Strcmp(token, "setpassword")) {
  519.         rv = putStringToStream(stream,
  520.                    XP_GetString(XP_SEC_SETPASSWORD),
  521.                    quote);
  522.         if (rv) {
  523.         return(SECFailure);
  524.         }
  525.     }
  526.     else if (!PORT_Strcmp(token, "fetch")) {
  527.         rv = putStringToStream(stream,
  528.                    XP_GetString(XP_SEC_FETCH),
  529.                    quote);
  530.         if (rv) {
  531.         return(SECFailure);
  532.         }
  533.     }
  534.     else if (!PORT_Strcmp(token, "banner-sec")) {
  535.         rv = putStringToStream(stream,
  536.                    "<table width=100%><tr><td bgcolor=#0000ff><img align=left src=about:security?banner-secure></td></tr></table><br>",
  537.                    quote);
  538.         if (rv) {
  539.         return(SECFailure);
  540.         }
  541.     }
  542.     else if (!PORT_Strcmp(token, "saveas")) {
  543.         rv = putStringToStream(stream,
  544.                    XP_GetString(XP_SEC_SAVEAS),
  545.                    quote);
  546.         if (rv) {
  547.         return(SECFailure);
  548.         }
  549.     }
  550.     else if (!PORT_Strcmp(token, "-styleinfo-")) {
  551.         rv = putStringToStream(stream,
  552.             XP_GetString(XP_DIALOG_STYLEINFO_STRING), quote);
  553.         if(rv) {
  554.         return(SECFailure);
  555.         }
  556.     }
  557.     else if (!PORT_Strcmp(token, "sec-banner-begin")) {
  558.         rv = putStringToStream(stream,
  559.             "<table><tr><td>"
  560.             "<img align=left src=about:security?banner-secure></td>"
  561.             "<td>", quote);
  562.         if (rv) {
  563.         return(SECFailure);
  564.         }
  565.         rv = putStringToStream(stream,
  566.                 XP_GetString(XP_BANNER_FONTFACE_INFO_STRING),
  567.                 quote);
  568.         if (rv) {
  569.         return(SECFailure);
  570.         }
  571.         rv = putStringToStream(stream, "<B>", quote);
  572.         if (rv) {
  573.         return(SECFailure);
  574.         }
  575.     } else if (!PORT_Strcmp(token, "sec-banner-end")) {
  576.         rv = putStringToStream(stream,
  577.             "</b></font></td></tr></table><br>", quote);
  578.         if (rv) {
  579.         return(SECFailure);
  580.         }
  581.     }
  582.     else {
  583.         PORT_Assert(0);    /* Failure: Unhandled token. */
  584.     }
  585.     
  586.     *src = '%';        /* non-destructive... */
  587.     src++;            /* now points past %..% */
  588.     }
  589.     
  590.     rv = putStringToStream(stream, src, quote);
  591.     if (rv) {
  592.      return(SECFailure);
  593.     }
  594.     
  595.     return(SECSuccess);
  596. }
  597.  
  598. SECStatus
  599. XP_PutDialogStringsTagToStream(HTMLDialogStream *stream, int num, PRBool quote)
  600. {
  601.     SECStatus rv;
  602.     XPDialogStrings *strings;
  603.     
  604.     strings = XP_GetDialogStrings(num);
  605.     if ( strings == NULL ) {
  606.     return(SECFailure);
  607.     }
  608.     
  609.     rv = XP_PutDialogStringsToStream(stream, strings, quote);
  610.     
  611.     XP_FreeDialogStrings(strings);
  612.     
  613.     return(rv);
  614. }
  615.  
  616. char **
  617. cgi_ConvertStringToArgVec(char *str, int length, int *argcp)
  618. {
  619.     char *cp, **avp;
  620.     int argc;
  621.     char c;
  622.     char tmp;
  623.     char *destp;
  624.     
  625.     char **av = 0;
  626.     if (!str) {
  627.     if (argcp) *argcp = 0;
  628.     return 0;
  629.     }
  630.  
  631.     cp = str + length - 1;
  632.     while ( (*cp == '\n') || (*cp == '\r') ) {
  633.     *cp-- = '\0';
  634.     }
  635.     
  636.     /* 1. Count number of args in input */
  637.     argc = 1;
  638.     cp = str;
  639.     for (;;) {
  640.     cp = PORT_Strchr(cp, '=');
  641.     if (!cp) break;
  642.     cp++;
  643.     argc++;
  644.     cp = PORT_Strchr(cp, '&');
  645.     if (!cp) break;
  646.     cp++;
  647.     argc++;
  648.     }
  649.  
  650.     /* 2. Allocate space for argvec array and copy of strings */
  651.     *argcp = argc;
  652.     av = (char**) PORT_ZAlloc(((argc + 1) * sizeof(char*)) + strlen(str) + 1);
  653.     destp = ((char *)av) + ( (argc + 1) * sizeof(char *) );
  654.     
  655.     if (!av) goto loser;
  656.  
  657.     /*
  658.     ** 3. Break up input into each arg chunk. Once we break an entry up,
  659.     ** compress it in place, replacing the magic characters with their
  660.     ** correct value.
  661.     */
  662.     avp = av;
  663.     cp = str;
  664.     *avp++ = destp;
  665.  
  666.     while( ( c = (*cp++) ) != '\0' ) {
  667.     switch( c ) {
  668.       case '&':
  669.       case '=':
  670.         *destp++ = '\0';
  671.         *avp++ = destp;
  672.         break;
  673.       case '+':
  674.         *destp++ = ' ';
  675.         break;
  676.       case '%':
  677.         c = *cp++;
  678.         if ((c >= 'a') && (c <= 'f')) {
  679.         tmp = c - 'a' + 10;
  680.         } else if ((c >= 'A') && (c <= 'F')) {
  681.         tmp = c - 'A' + 10;
  682.         } else {
  683.         tmp = c - '0';
  684.         }
  685.         tmp = tmp << 4;
  686.         c = *cp++;
  687.         if ((c >= 'a') && (c <= 'f')) {
  688.         tmp |= ( c - 'a' + 10 );
  689.         } else if ((c >= 'A') && (c <= 'F')) {
  690.         tmp |= ( c - 'A' + 10 );
  691.         } else {
  692.         tmp |= ( c - '0' );
  693.         }
  694.         *destp++ = tmp;
  695.         break;
  696.       default:
  697.         *destp++ = c;
  698.         break;
  699.     }
  700.     *destp = '\0';
  701.     }
  702.     return av;
  703.  
  704.   loser:
  705.     PORT_Free(av);
  706.     return 0;
  707. }
  708.  
  709. /*
  710.  * return the value of a name value pair
  711.  */
  712. char *
  713. XP_FindValueInArgs(const char *name, char **av, int ac)
  714. {
  715.     for( ;ac > 0; ac -= 2, av += 2 ) {
  716.     if ( PORT_Strcmp(name, av[0]) == 0 ) {
  717.         return(av[1]);
  718.     }
  719.     }
  720.     return(0);
  721. }
  722.  
  723. void
  724. XP_HandleHTMLDialog(URL_Struct *url)
  725. {
  726.     char **av = NULL;
  727.     int ac;
  728.     char *handleString;
  729.     char *buttonString;
  730.     XPDialogState *handle = NULL;
  731.     unsigned int button;
  732.     PRBool ret;
  733.     
  734.     /* collect post data */
  735.     av = cgi_ConvertStringToArgVec(url->post_data, url->post_data_size, &ac);
  736.     if ( av == NULL ) {
  737.     goto loser;
  738.     }
  739.     
  740.     /* get the handle */
  741.     handleString = XP_FindValueInArgs("handle", av, ac);
  742.     if ( handleString == NULL ) {
  743.     goto loser;
  744.     }
  745.  
  746.     /* get the button value */
  747.     buttonString = XP_FindValueInArgs("button", av, ac);
  748.     if ( buttonString == NULL ) {
  749.     goto loser;
  750.     }
  751.  
  752.     handle = NULL;
  753. #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */
  754.     sscanf(handleString, "%lu", &handle);
  755. #else
  756.     sscanf(handleString, "%p", &handle);
  757.  #endif
  758.     if ( handle == NULL ) {
  759.     goto loser;
  760.     }
  761.  
  762.     if ( handle->deleted ) {
  763.     goto loser;
  764.     }
  765.     
  766.     if ( PORT_Strcasecmp(buttonString, XP_GetString(XP_SEC_OK)) == 0 ) {
  767.     button = XP_DIALOG_OK_BUTTON;
  768.     } else if ( PORT_Strcasecmp(buttonString,
  769.                   XP_GetString(XP_SEC_CANCEL)) == 0 ) {
  770.     button = XP_DIALOG_CANCEL_BUTTON;
  771.     } else if ( PORT_Strcasecmp(buttonString,
  772.                   XP_GetString(XP_SEC_CONTINUE)) == 0 ) {
  773.     button = XP_DIALOG_CONTINUE_BUTTON;
  774.     } else if ( PORT_Strcasecmp(buttonString,
  775.                   XP_GetString(XP_SEC_MOREINFO)) == 0 ) {
  776.     button = XP_DIALOG_MOREINFO_BUTTON;
  777.     } else if ( PORT_Strcasecmp(buttonString,
  778.                   XP_GetString(XP_SEC_FETCH)) == 0 ) {
  779.     button = XP_DIALOG_FETCH_BUTTON;
  780.     } else {
  781.     button = 0;
  782.     }
  783.  
  784.     /* call the application handler */
  785.     ret = PR_FALSE;
  786.     if ( handle->dialogInfo->handler != NULL ) {
  787.     ret = (* handle->dialogInfo->handler)(handle, av, ac, button);
  788.     }
  789.  
  790. loser:
  791.  
  792.     /* free arg vector */
  793.     if ( av != NULL ) {
  794.     PORT_Free(av);
  795.     }
  796.  
  797.     if ( ( handle != NULL ) && ( ret == PR_FALSE ) && ( !handle->deleted ) ) {
  798.     deleteWindowCBArg *delstate;
  799.     
  800.     /* set callback to destroy the window */
  801.     delstate = (deleteWindowCBArg *)PORT_Alloc(sizeof(deleteWindowCBArg));
  802.     if ( delstate ) {
  803.         delstate->window = (void *)handle->window;
  804.         delstate->arg = handle->cbarg;
  805.         delstate->deleteWinCallback = handle->deleteCallback;
  806.         delstate->freeArena = handle->arena;
  807.         (void)FE_SetTimeout(deleteWindow, (void *)delstate, 0);
  808.     }
  809.     
  810.     handle->deleted = PR_TRUE;
  811.     }
  812.     
  813.     return;
  814. }
  815.  
  816. void
  817. xp_InitChrome(void *proto_win, Chrome *chrome, int width, int height,
  818.           PRBool isModal)
  819. {
  820.     PORT_Memset(chrome, 0, sizeof(Chrome));
  821.     chrome->type = MWContextDialog;
  822.     chrome->w_hint = width;
  823.     chrome->h_hint = height;
  824.  
  825.     chrome->is_modal = TRUE;
  826.     
  827.     /* Try to make the dialog fit on the screen, centered over the proto_win */
  828.     if ( proto_win && chrome->w_hint && chrome->h_hint ) {
  829.         int32 screenWidth = 0;
  830.         int32 screenHeight = 0;
  831.         
  832.         Chrome protoChrome;
  833.     
  834.         PORT_Memset(&protoChrome, 0, sizeof(protoChrome));
  835.         
  836.         /* We want to shrink the dialog to fit on the screen if necessary.
  837.          *
  838.          * The inner dimensions of the dialog have to be specified in the
  839.      * Chrome. However, we want to OUTER dimensions to fit on the screen.
  840.          * We don't know the difference between the inner and outer dimensions.
  841.          * We could try to find that difference information from the
  842.      * proto_win's Chrome structure, but the proto_win probably has
  843.      * a completely different structure from our dialog windows. So we
  844.      * just guess...
  845.          */
  846.         FE_GetScreenSize ((MWContext *) proto_win, &screenWidth,
  847.               &screenHeight);
  848.         
  849.         if ( screenWidth && screenHeight ) {
  850.         /* arbitrary slop around dialog */
  851.             if (chrome->w_hint > screenWidth - 20)
  852.                 chrome->w_hint = screenWidth - 20;
  853.             if (chrome->h_hint > screenHeight - 30)
  854.                 chrome->h_hint = screenHeight - 30;
  855.         }
  856.  
  857.         /* Now, try to find out where the proto_win is so we can center on it.
  858.      */
  859.         FE_QueryChrome((MWContext *)proto_win, &protoChrome);
  860.         
  861.         /* Did we get anything useful? */
  862.         if ( protoChrome.location_is_chrome && protoChrome.w_hint &&
  863.         protoChrome.h_hint ) {
  864.             chrome->location_is_chrome = TRUE;
  865.             chrome->l_hint = protoChrome.l_hint +
  866.         (protoChrome.w_hint - chrome->w_hint) / 2;
  867.             chrome->t_hint = protoChrome.t_hint +
  868.         (protoChrome.h_hint - chrome->h_hint) / 2;
  869.         }
  870.         
  871.         /* If we moved the dialog, make sure we didn't move it off the screen.
  872.      */
  873.         if ( chrome->location_is_chrome && screenWidth && screenHeight ) {
  874.             if ( chrome->l_hint < 0) {
  875.                 chrome->l_hint = 0;
  876.         }
  877.             if ( chrome->t_hint < 0) {
  878.                 chrome->t_hint = 0;
  879.         }
  880.             if ( chrome->l_hint > ( screenWidth - chrome->w_hint ) ) {
  881.                 chrome->l_hint = screenWidth - chrome->w_hint;
  882.         }
  883.             if ( chrome->t_hint > ( screenHeight - chrome->h_hint ) ) {
  884.                 chrome->t_hint = screenHeight - chrome->h_hint;
  885.         }
  886.         }
  887.     }
  888.     
  889.     return;
  890. }
  891.  
  892.  
  893. XPDialogState *
  894. XP_MakeHTMLDialog(void *proto_win, XPDialogInfo *dialogInfo, 
  895.           int titlenum, XPDialogStrings *strings, void *arg,
  896.           PRBool utf8CharSet)
  897. {
  898.     Chrome chrome;
  899.  
  900.     xp_InitChrome(proto_win, &chrome, dialogInfo->width,
  901.           dialogInfo->height, PR_TRUE);
  902.     
  903.     return(XP_MakeHTMLDialogWithChrome(proto_win, dialogInfo, titlenum, 
  904.                        strings, &chrome, arg, utf8CharSet));
  905. }
  906.  
  907. void
  908. freeHTMLDialogStream(HTMLDialogStream *stream)
  909. {
  910.     if ( stream != NULL ) {
  911.     if ( stream->stream != NULL ) {
  912.         PORT_Free(stream->stream);
  913.     }
  914.     
  915.     if ( stream->url != NULL ) {
  916.         NET_FreeURLStruct(stream->url);
  917.     }
  918.     
  919.     if ( stream->arena != NULL ) {
  920.         PORT_FreeArena(stream->arena, PR_FALSE);
  921.     }
  922.     }
  923.     
  924.     return;
  925. }
  926.  
  927. HTMLDialogStream *
  928. newHTMLDialogStream(void *cx)
  929. {
  930.     HTMLDialogStream *stream;
  931.     PRArenaPool *arena;
  932.  
  933.     arena = PORT_NewArena(512);
  934.     if ( arena == NULL ) {
  935.     goto loser;
  936.     }
  937.  
  938.     /* make an html dialog stream */
  939.     stream = (HTMLDialogStream *)PORT_ArenaZAlloc(arena,
  940.                           sizeof(HTMLDialogStream));
  941.     if ( stream == NULL ) {
  942.     goto loser;
  943.     }
  944.  
  945.     stream->arena = arena;
  946.     
  947.     /* initialize the list of queued buffers */
  948.     PR_INIT_CLIST(&stream->queuedBuffers);
  949.     
  950.     /* create a URL struct */
  951.     stream->url = NET_CreateURLStruct("", NET_DONT_RELOAD);
  952.     if ( stream->url == NULL ) {
  953.     goto loser;
  954.     }
  955.     StrAllocCopy(stream->url->content_type, TEXT_HTML);
  956.     
  957.     /* make a netlib stream to display in the window */
  958.     stream->stream = NET_StreamBuilder(FO_PRESENT, stream->url, cx);
  959.     if ( stream->stream == NULL ) {
  960.     goto loser;
  961.     }
  962.     
  963.     return(stream);
  964.     
  965. loser:
  966.  
  967.     freeHTMLDialogStream(stream);
  968.     
  969.     return(NULL);
  970. }
  971.  
  972. void
  973. emptyQueues(void *arg)
  974. {
  975.     HTMLDialogStream *stream;
  976.     bufferNode *node;
  977.     unsigned int cnt;
  978.     int ret;
  979.     
  980.     stream = (HTMLDialogStream *)arg;
  981.  
  982.     while ( ! PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) {
  983.     /* get the head node */
  984.     node = (bufferNode *)PR_LIST_HEAD(&stream->queuedBuffers);
  985.  
  986.     cnt = (*(stream->stream)->is_write_ready)(stream->stream);
  987.  
  988.     if ( cnt < node->len ) {
  989.         /* layout hasn't unclogged yet */
  990.         break;
  991.     }
  992.     
  993.     ret = (*(stream->stream)->put_block)(stream->stream,
  994.                          node->data, node->len);
  995.     if ( ret < 0 ) {
  996.         goto loser;
  997.     }
  998.     
  999.     /* remove it from the list */
  1000.     PR_REMOVE_LINK(&node->link);
  1001.     }
  1002.     
  1003.     if ( PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) {
  1004.     (*stream->stream->complete) (stream->stream);
  1005.     freeHTMLDialogStream(stream);
  1006.     } else {
  1007.     FE_SetTimeout(emptyQueues, (void *)stream, 100);
  1008.     }
  1009.     
  1010.     return;
  1011.  
  1012. loser:
  1013.     freeHTMLDialogStream(stream);
  1014.     return;
  1015. }
  1016.  
  1017. void *
  1018. xp_MakeHTMLDialogWindow(void *proto_win, Chrome *chrome)
  1019. {
  1020.     MWContext *cx;
  1021.     
  1022.     /* make the window */
  1023.     cx = FE_MakeNewWindow((MWContext *)proto_win, NULL, NULL, chrome);
  1024.     if ( cx == NULL ) {
  1025.     goto done;
  1026.     }
  1027.  
  1028.     LM_ForceJSEnabled(cx);
  1029.  
  1030.     /* XXX - get rid of session history */
  1031.     SHIST_EndSession(cx);
  1032.     PORT_Memset((void *)&cx->hist, 0, sizeof(cx->hist));
  1033.  
  1034. done:
  1035.     return(cx);
  1036. }
  1037.  
  1038. SECStatus
  1039. xp_DrawHTMLDialog(void *cx, XPDialogInfo *dialogInfo,
  1040.           int titlenum, XPDialogStrings *strings,
  1041.           void *state, PRBool utf8CharSet)
  1042. {
  1043.     HTMLDialogStream *stream = NULL;
  1044.     SECStatus rv;
  1045.     char buf[50];
  1046.     XPDialogStrings *dlgstrings;
  1047.     int buttontag;
  1048.     
  1049.     /* make the stream */
  1050.     stream = newHTMLDialogStream(cx);
  1051.     if ( stream == NULL ) {
  1052.     goto loser;
  1053.     }
  1054.     
  1055.     if ( utf8CharSet ) {
  1056.     dlgstrings =
  1057.         XP_GetDialogStrings(XP_DIALOG_JS_HEADER_STRINGS_WITH_UTF8_CHARSET);
  1058.     } else {
  1059.     dlgstrings = XP_GetDialogStrings(XP_DIALOG_JS_HEADER_STRINGS);
  1060.     }
  1061.     
  1062.     if ( dlgstrings == NULL ) {
  1063.     goto loser;
  1064.     }
  1065.  
  1066.     /* put the title in header */
  1067.     XP_CopyDialogString(dlgstrings, 0, XP_GetString(titlenum));
  1068.  
  1069.     /* send html header stuff */
  1070.     rv = XP_PutDialogStringsToStream(stream, dlgstrings, PR_FALSE);
  1071.     XP_FreeDialogStrings(dlgstrings);
  1072.     
  1073.     if ( rv != SECSuccess ) {
  1074.     goto loser;
  1075.     }
  1076.  
  1077.     dlgstrings = XP_GetDialogStrings(XP_DIALOG_HEADER_STRINGS);
  1078.     if ( dlgstrings == NULL ) {
  1079.     goto loser;
  1080.     }
  1081.  
  1082.     /* put handle in header */
  1083. #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */
  1084.     sprintf(buf, "%lu", state);
  1085. #else
  1086.     sprintf(buf, "%p", state);
  1087. #endif
  1088.     XP_SetDialogString(dlgstrings, 0, buf);
  1089.     
  1090.     /* send html header stuff */
  1091.     rv = XP_PutDialogStringsToStream(stream, dlgstrings, PR_TRUE);
  1092.     XP_FreeDialogStrings(dlgstrings);
  1093.     
  1094.     if ( rv != SECSuccess ) {
  1095.     goto loser;
  1096.     }
  1097.  
  1098.     /* send caller's message */
  1099.     rv = XP_PutDialogStringsToStream(stream, strings, PR_TRUE);
  1100.  
  1101.     if ( rv != SECSuccess ) {
  1102.     goto loser;
  1103.     }
  1104.  
  1105.     /* send trailing info */
  1106.     rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_FOOTER_STRINGS,
  1107.                     PR_TRUE);
  1108.  
  1109.     if ( rv != SECSuccess ) {
  1110.     goto loser;
  1111.     }
  1112.  
  1113.     /* send button strings */
  1114.     switch(dialogInfo->buttonFlags) {
  1115.       case XP_DIALOG_CANCEL_BUTTON:
  1116.     buttontag = XP_DIALOG_CANCEL_BUTTON_STRINGS;
  1117.     break;
  1118.       case XP_DIALOG_CONTINUE_BUTTON:
  1119.     buttontag = XP_DIALOG_CONTINUE_BUTTON_STRINGS;
  1120.     break;
  1121.       case XP_DIALOG_OK_BUTTON:
  1122.     buttontag = XP_DIALOG_OK_BUTTON_STRINGS;
  1123.     break;
  1124.       case XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_OK_BUTTON:
  1125.     buttontag = XP_DIALOG_CANCEL_OK_BUTTON_STRINGS;
  1126.     break;
  1127.       case XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_CONTINUE_BUTTON:
  1128.     buttontag = XP_DIALOG_CANCEL_CONTINUE_BUTTON_STRINGS;
  1129.     break;
  1130.       case XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_OK_BUTTON |
  1131.       XP_DIALOG_MOREINFO_BUTTON:
  1132.     buttontag = XP_DIALOG_CANCEL_OK_MOREINFO_BUTTON_STRINGS;
  1133.     break;
  1134.       case XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_FETCH_BUTTON:
  1135.     buttontag = XP_DIALOG_FETCH_CANCEL_BUTTON_STRINGS;
  1136.     break;
  1137.       default:
  1138.     buttontag = XP_DIALOG_NULL_STRINGS;
  1139.     break;
  1140.     }
  1141.  
  1142.     rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_JS_MIDDLE_STRINGS,
  1143.                     PR_FALSE);
  1144.     if ( rv != SECSuccess ) {
  1145.     goto loser;
  1146.     }
  1147.  
  1148.     rv = XP_PutDialogStringsTagToStream(stream, buttontag, PR_TRUE);
  1149.     if ( rv != SECSuccess ) {
  1150.     goto loser;
  1151.     }
  1152.  
  1153.     rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_JS_FOOTER_STRINGS,
  1154.                     PR_FALSE);
  1155.     if ( rv != SECSuccess ) {
  1156.     goto loser;
  1157.     }
  1158.  
  1159.     if ( PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) {
  1160.     /* complete the stream */
  1161.     (*stream->stream->complete) (stream->stream);
  1162.  
  1163.     freeHTMLDialogStream(stream);
  1164.     return(SECSuccess);
  1165.     } else {
  1166.     FE_SetTimeout(emptyQueues, (void *)stream, 0);
  1167.     return(SECSuccess);
  1168.     }
  1169.     
  1170. loser:    
  1171.     /* XXX free URL and CX ???*/
  1172.  
  1173.     /* abort the stream */
  1174.     if ( stream != NULL ) {
  1175.     if ( stream->stream != NULL ) {
  1176.         (*stream->stream->abort)(stream->stream, rv);
  1177.     }
  1178.     }
  1179.  
  1180.     freeHTMLDialogStream(stream);
  1181.     
  1182.     return(SECFailure);
  1183. }
  1184.  
  1185. XPDialogState *
  1186. XP_MakeHTMLDialogWithChrome(void *proto_win, XPDialogInfo *dialogInfo,
  1187.                 int titlenum, XPDialogStrings *strings,
  1188.                 Chrome *chrome, void *arg, PRBool utf8CharSet)
  1189. {
  1190.     void *cx;
  1191.     SECStatus rv;
  1192.     XPDialogState *state;
  1193.     PRArenaPool *arena = NULL;
  1194.     
  1195.     arena = PORT_NewArena(1024);
  1196.     
  1197.     if ( arena == NULL ) {
  1198.     return(NULL);
  1199.     }
  1200.  
  1201.     /* allocate the state structure */
  1202.     state = (XPDialogState *)PORT_ArenaAlloc(arena, sizeof(XPDialogState));
  1203.     if ( state == NULL ) {
  1204.     goto loser;
  1205.     }
  1206.     
  1207.     state->deleted = PR_FALSE;
  1208.     state->arena = arena;
  1209.     state->dialogInfo = dialogInfo;
  1210.     state->arg = arg;
  1211.     state->deleteCallback = NULL;
  1212.     state->cbarg = NULL;
  1213.     state->proto_win = proto_win;
  1214.  
  1215.     state->window = xp_MakeHTMLDialogWindow(proto_win, chrome);
  1216.     if ( state->window == NULL ) {
  1217.     goto loser;
  1218.     }
  1219.     
  1220.     rv = xp_DrawHTMLDialog(state->window, dialogInfo, titlenum, strings,
  1221.                (void *)state, utf8CharSet);
  1222.     
  1223.     if ( rv != SECSuccess ) {
  1224.     goto loser;
  1225.     }
  1226.  
  1227.     return(state);
  1228.     
  1229. loser:
  1230.     PORT_FreeArena(arena, PR_FALSE);
  1231.     return(NULL);
  1232. }
  1233.  
  1234. void *
  1235. xp_MakeHTMLDialogPass1(void *proto_win, XPDialogInfo *dialogInfo)
  1236. {
  1237.     Chrome chrome;
  1238.  
  1239.     xp_InitChrome(proto_win, &chrome, dialogInfo->width,
  1240.           dialogInfo->height, PR_TRUE);
  1241.  
  1242.     return(xp_MakeHTMLDialogWindow(proto_win, &chrome));
  1243. }
  1244.  
  1245. XPDialogState *
  1246. xp_MakeHTMLDialogPass2(void *proto_win, void *cx, XPDialogInfo *dialogInfo,
  1247.                int titlenum, XPDialogStrings *strings,
  1248.                void *arg, PRBool utf8CharSet)
  1249. {
  1250.     SECStatus rv;
  1251.     XPDialogState *state;
  1252.     PRArenaPool *arena = NULL;
  1253.     
  1254.     arena = PORT_NewArena(1024);
  1255.     
  1256.     if ( arena == NULL ) {
  1257.     return(NULL);
  1258.     }
  1259.  
  1260.     /* allocate the state structure */
  1261.     state = (XPDialogState *)PORT_ArenaAlloc(arena, sizeof(XPDialogState));
  1262.     if ( state == NULL ) {
  1263.     goto loser;
  1264.     }
  1265.     
  1266.     state->deleted = PR_FALSE;
  1267.     state->arena = arena;
  1268.     state->dialogInfo = dialogInfo;
  1269.     state->arg = arg;
  1270.     state->deleteCallback = NULL;
  1271.     state->cbarg = NULL;
  1272.     state->proto_win = proto_win;
  1273.  
  1274.     state->window = cx;
  1275.     
  1276.     rv = xp_DrawHTMLDialog(state->window, dialogInfo, titlenum, strings,
  1277.                (void *)state, utf8CharSet);
  1278.     
  1279.     if ( rv != SECSuccess ) {
  1280.     goto loser;
  1281.     }
  1282.  
  1283.     return(state);
  1284.     
  1285. loser:
  1286.     PORT_FreeArena(arena, PR_FALSE);
  1287.     return(NULL);
  1288. }
  1289.  
  1290. int
  1291. XP_RedrawRawHTMLDialog(XPDialogState *state,
  1292.                XPDialogStrings *strings,
  1293.                int handlestring)
  1294. {
  1295.     HTMLDialogStream *stream = NULL;
  1296.     SECStatus rv;
  1297.     char buf[50];
  1298.  
  1299.     stream = newHTMLDialogStream(state->window);
  1300.     if ( stream == NULL ) {
  1301.     goto loser;
  1302.     }
  1303.     
  1304.     /* put handle in header */
  1305. #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */
  1306.     sprintf(buf, "%lu", state);
  1307. #else
  1308.     sprintf(buf, "%p", state);
  1309. #endif
  1310.     XP_SetDialogString(strings, handlestring, buf);
  1311.     
  1312.     /* send caller's message */
  1313.     rv = XP_PutDialogStringsToStream(stream, strings, PR_FALSE);
  1314.  
  1315.     if ( rv != SECSuccess ) {
  1316.     goto loser;
  1317.     }
  1318.  
  1319.     /* complete the stream */
  1320.     if ( PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) {
  1321.     /* complete the stream */
  1322.     (*stream->stream->complete) (stream->stream);
  1323.  
  1324.     freeHTMLDialogStream(stream);
  1325.     return((int)SECSuccess);
  1326.     } else {
  1327.     FE_SetTimeout(emptyQueues, (void *)stream, 0);
  1328.     return((int)SECSuccess);
  1329.     }
  1330.  
  1331. loser:    
  1332.     /* XXX free URL and CX ???*/
  1333.  
  1334.     /* abort the stream */
  1335.     if ( stream != NULL ) {
  1336.     if ( stream->stream != NULL ) {
  1337.         (*stream->stream->abort)(stream->stream, rv);
  1338.     }
  1339.     }
  1340.  
  1341.     freeHTMLDialogStream(stream);
  1342.  
  1343.     return((int)SECFailure);
  1344. }
  1345.  
  1346. /*    ***** What a hack!!! Make the security advisor modeless on the Mac. ***** */
  1347. #ifdef XP_MAC
  1348. extern int XP_SECURITY_ADVISOR_TITLE_STRING;
  1349. #endif
  1350. XPDialogState *
  1351. XP_MakeRawHTMLDialog(void *proto_win, XPDialogInfo *dialogInfo,
  1352.              int titlenum, XPDialogStrings *strings,
  1353.              int handlestring, void *arg)
  1354. {
  1355.     MWContext *cx = NULL;
  1356.     SECStatus rv;
  1357.     XPDialogState *state;
  1358.     PRArenaPool *arena = NULL;
  1359.     Chrome chrome;
  1360.     PORT_Memset(&chrome, 0, sizeof(chrome));
  1361.     chrome.type = MWContextDialog;
  1362.     chrome.w_hint = dialogInfo->width;
  1363.     chrome.h_hint = dialogInfo->height;
  1364. /*    ***** What a hack!!! Make the security advisor modeless on the Mac. ***** */
  1365. #ifdef XP_MAC
  1366.     chrome.is_modal = (titlenum == XP_SECURITY_ADVISOR_TITLE_STRING) ? FALSE : TRUE;
  1367. #else
  1368.     chrome.is_modal = TRUE;
  1369. #endif
  1370.     
  1371.     arena = PORT_NewArena(1024);
  1372.     
  1373.     if ( arena == NULL ) {
  1374.     return(NULL);
  1375.     }
  1376.  
  1377.     /* allocate the state structure */
  1378.     state = (XPDialogState *)PORT_ArenaAlloc(arena, sizeof(XPDialogState));
  1379.     if ( state == NULL ) {
  1380.     goto loser;
  1381.     }
  1382.     
  1383.     state->deleted = PR_FALSE;
  1384.     state->arena = arena;
  1385.     state->dialogInfo = dialogInfo;
  1386.     state->arg = arg;
  1387.     state->deleteCallback = NULL;
  1388.     state->cbarg = NULL;
  1389.     
  1390.     /* make the window */
  1391. /*    ***** What a hack!!! Make the security advisor modeless on the Mac. ***** */
  1392. #ifdef XP_MAC
  1393.     if (titlenum == XP_SECURITY_ADVISOR_TITLE_STRING)
  1394.         cx = FE_MakeNewWindow((MWContext *)proto_win, NULL, XP_GetString(titlenum), &chrome);
  1395.     else
  1396. #else
  1397.     cx = FE_MakeNewWindow((MWContext *)proto_win, NULL, NULL, &chrome);
  1398. #endif
  1399.     if ( cx == NULL ) {
  1400.     goto loser;
  1401.     }
  1402.     LM_ForceJSEnabled(cx);
  1403.     
  1404.     state->window = (void *)cx;
  1405.     state->proto_win = proto_win;
  1406.  
  1407.     /* XXX - get rid of session history */
  1408.     SHIST_EndSession(cx);
  1409.     PORT_Memset((void *)&cx->hist, 0, sizeof(cx->hist));
  1410.  
  1411.     rv = (SECStatus)XP_RedrawRawHTMLDialog(state, strings, handlestring);
  1412.  
  1413.     if ( rv != SECSuccess ) {
  1414.     goto loser;
  1415.     }
  1416.     return(state);
  1417.  
  1418. loser:
  1419.     /* free the arena */
  1420.     if ( arena != NULL ) {
  1421.     PORT_FreeArena(arena, PR_FALSE);
  1422.     }
  1423.     
  1424.     return(NULL);
  1425. }
  1426.  
  1427. static void
  1428. displayPanelCB(void *arg)
  1429. {
  1430.     XPPanelState *state;
  1431.     HTMLDialogStream *stream;
  1432.     XPDialogStrings *contentstrings;
  1433.     SECStatus rv;
  1434.     char buf[50];
  1435.     XPDialogStrings *dlgstrings;
  1436.     int buttontag;
  1437.     
  1438.     state = (XPPanelState *)arg;
  1439.     
  1440.     stream = newHTMLDialogStream(state->window);
  1441.     if (stream == NULL) {
  1442.     goto loser;
  1443.     }
  1444.  
  1445.     dlgstrings = XP_GetDialogStrings(XP_DIALOG_JS_HEADER_STRINGS);
  1446.     
  1447.     if ( dlgstrings == NULL ) {
  1448.     goto loser;
  1449.     }
  1450.  
  1451.     /* put the title in header */
  1452.     XP_CopyDialogString(dlgstrings, 0, XP_GetString(state->titlenum));
  1453.  
  1454.     /* send html header stuff */
  1455.     rv = XP_PutDialogStringsToStream(stream, dlgstrings, PR_FALSE);
  1456.     XP_FreeDialogStrings(dlgstrings);
  1457.     
  1458.     if ( rv != SECSuccess ) {
  1459.     goto loser;
  1460.     }
  1461.  
  1462.     /* get header strings */
  1463.     dlgstrings = XP_GetDialogStrings(XP_PANEL_HEADER_STRINGS);
  1464.     if ( dlgstrings == NULL ) {
  1465.     goto loser;
  1466.     }
  1467.  
  1468.     /* put handle in header */
  1469. #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */
  1470.     sprintf(buf, "%lu", state);
  1471. #else
  1472.     sprintf(buf, "%p", state);
  1473. #endif
  1474.     XP_SetDialogString(dlgstrings, 0, buf);
  1475.     
  1476.     /* send html header stuff */
  1477.     rv = XP_PutDialogStringsToStream(stream, dlgstrings, PR_TRUE);
  1478.  
  1479.     /* free the strings */
  1480.     XP_FreeDialogStrings(dlgstrings);
  1481.     
  1482.     if ( rv != SECSuccess ) {
  1483.     goto loser;
  1484.     }
  1485.  
  1486.     /* send panel message */
  1487.     contentstrings = (* state->panels[state->curPanel].content)(state);
  1488.     if ( contentstrings == NULL ) {
  1489.     goto loser;
  1490.     }
  1491.     
  1492.     state->curStrings = contentstrings;
  1493.     
  1494.     rv = XP_PutDialogStringsToStream(stream, contentstrings, PR_TRUE);
  1495.     if ( rv != SECSuccess ) {
  1496.     goto loser;
  1497.     }
  1498.  
  1499.     XP_FreeDialogStrings(contentstrings);
  1500.  
  1501.     /* send html middle stuff */
  1502.     rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_FOOTER_STRINGS,
  1503.                     PR_TRUE);
  1504.     if ( rv != SECSuccess ) {
  1505.     goto loser;
  1506.     }
  1507.     if ( state->panels[state->curPanel].flags & XP_PANEL_FLAG_ONLY ) {
  1508.     /* if its the only panel */
  1509.     buttontag = XP_PANEL_ONLY_BUTTON_STRINGS;
  1510.     } else if ( ( state->curPanel == ( state->panelCount - 1 ) ) ||
  1511.     ( state->panels[state->curPanel].flags & XP_PANEL_FLAG_FINAL ) ) {
  1512.     /* if its the last panel or has the final flag set */
  1513.     buttontag = XP_PANEL_LAST_BUTTON_STRINGS;
  1514.     } else if ( ( state->curPanel == 0 ) ||
  1515.     ( state->panels[state->curPanel].flags & XP_PANEL_FLAG_FIRST ) ) {
  1516.     buttontag = XP_PANEL_FIRST_BUTTON_STRINGS;
  1517.     } else {
  1518.     buttontag = XP_PANEL_MIDDLE_BUTTON_STRINGS;
  1519.     }
  1520.     
  1521.     rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_JS_MIDDLE_STRINGS,
  1522.                     PR_FALSE);
  1523.     if ( rv != SECSuccess ) {
  1524.     goto loser;
  1525.     }
  1526.  
  1527.     /* send button strings */
  1528.     rv = XP_PutDialogStringsTagToStream(stream, buttontag, PR_TRUE);
  1529.     if ( rv != SECSuccess ) {
  1530.     goto loser;
  1531.     }
  1532.  
  1533.     rv = XP_PutDialogStringsTagToStream(stream, XP_DIALOG_JS_FOOTER_STRINGS,
  1534.                     PR_FALSE);
  1535.     if ( rv != SECSuccess ) {
  1536.     goto loser;
  1537.     }
  1538.  
  1539.     /* complete the stream */
  1540.     if ( PR_CLIST_IS_EMPTY(&stream->queuedBuffers) ) {
  1541.     /* complete the stream */
  1542.     (*stream->stream->complete) (stream->stream);
  1543.  
  1544.     freeHTMLDialogStream(stream);
  1545.     return;
  1546.     } else {
  1547.     FE_SetTimeout(emptyQueues, (void *)stream, 0);
  1548.     return;
  1549.     }
  1550.     return;
  1551.  
  1552. loser:    
  1553.     /* abort the stream */
  1554.     if ( stream != NULL ) {
  1555.     if ( stream->stream != NULL ) {
  1556.         (*stream->stream->abort)(stream->stream, rv);
  1557.     }
  1558.     }
  1559.  
  1560.     freeHTMLDialogStream(stream);
  1561.  
  1562.     return;
  1563. }
  1564.  
  1565. static void
  1566. displayPanel(XPPanelState *state)
  1567. {
  1568.     (void)FE_SetTimeout(displayPanelCB, (void *)state, 0);
  1569. }
  1570.  
  1571. void
  1572. XP_MakeHTMLPanel(void *proto_win, XPPanelInfo *panelInfo,
  1573.          int titlenum, void *arg)
  1574. {
  1575.     PRArenaPool *arena;
  1576.     XPPanelState *state = NULL;
  1577.     Chrome chrome;
  1578.     MWContext *cx;
  1579.     
  1580.     arena = PORT_NewArena(1024);
  1581.     if ( arena == NULL ) {
  1582.     return;
  1583.     }
  1584.  
  1585.     state = (XPPanelState *)PORT_ArenaAlloc(arena, sizeof(XPPanelState));
  1586.     if ( state == NULL ) {
  1587.     return;
  1588.     }
  1589.     
  1590.     state->deleted = PR_FALSE;
  1591.     state->arena = arena;
  1592.     state->panels = panelInfo->desc;
  1593.     state->panelCount = panelInfo->panelCount;
  1594.     state->curPanel = 0;
  1595.     state->arg = arg;
  1596.     state->finish = panelInfo->finishfunc;
  1597.     state->info = panelInfo;
  1598.     state->titlenum = titlenum;
  1599.     state->deleteCallback = NULL;
  1600.     state->cbarg = NULL;
  1601.     
  1602.     /* make the window */
  1603.     PORT_Memset(&chrome, 0, sizeof(chrome));
  1604.     chrome.type = MWContextDialog;
  1605.     chrome.w_hint = panelInfo->width;
  1606.     chrome.h_hint = panelInfo->height;
  1607.     chrome.is_modal = TRUE;
  1608.     cx = FE_MakeNewWindow((MWContext *)proto_win, NULL, NULL, &chrome);
  1609.     state->window = (void *)cx;
  1610.     
  1611.     if ( state->window == NULL ) {
  1612.     PORT_FreeArena(arena, PR_FALSE);
  1613.     return;
  1614.     }
  1615.     LM_ForceJSEnabled(cx);
  1616.  
  1617.     /* XXX - get rid of session history */
  1618.     SHIST_EndSession(cx);
  1619.     PORT_Memset((void *)&cx->hist, 0, sizeof(cx->hist));
  1620.     
  1621.     /* display the first panel */
  1622.     displayPanel(state);
  1623.     
  1624.     return;
  1625. }
  1626.  
  1627. void
  1628. XP_HandleHTMLPanel(URL_Struct *url)
  1629. {
  1630.     char **av = NULL;
  1631.     int ac;
  1632.     char *handleString;
  1633.     char *buttonString;
  1634.     XPPanelState *state = NULL;
  1635.     unsigned int button;
  1636.     int nextpanel;
  1637.     
  1638.     /* collect post data */
  1639.     av = cgi_ConvertStringToArgVec(url->post_data, url->post_data_size, &ac);
  1640.     if ( av == NULL ) {
  1641.     goto loser;
  1642.     }
  1643.     
  1644.     /* get the handle */
  1645.     handleString = XP_FindValueInArgs("handle", av, ac);
  1646.     if ( handleString == NULL ) {
  1647.     goto loser;
  1648.     }
  1649.  
  1650.     /* get the button value */
  1651.     buttonString = XP_FindValueInArgs("button", av, ac);
  1652.     if ( buttonString == NULL ) {
  1653.     goto loser;
  1654.     }
  1655.  
  1656.     /* extract a handle pointer from the string */
  1657.     state = NULL;
  1658. #if defined(__sun) && !defined(SVR4) /* sun 4.1.3 */
  1659.     sscanf(handleString, "%lu", &state);
  1660. #else
  1661.     sscanf(handleString, "%p", &state);
  1662. #endif
  1663.     if ( state == NULL ) {
  1664.     goto loser;
  1665.     }
  1666.  
  1667.     if ( state->deleted ) {
  1668.     goto loser;
  1669.     }
  1670.     
  1671.     /* figure out which button was pressed */
  1672.     if ( PORT_Strcasecmp(buttonString,
  1673.                XP_GetString(XP_SEC_NEXT_KLUDGE)) == 0 ) {
  1674.     button = XP_DIALOG_NEXT_BUTTON;
  1675.     } else if ( PORT_Strcasecmp(buttonString,
  1676.                   XP_GetString(XP_SEC_CANCEL)) == 0 ) {
  1677.     button = XP_DIALOG_CANCEL_BUTTON;
  1678.     } else if ( PORT_Strcasecmp(buttonString,
  1679.                   XP_GetString(XP_SEC_BACK_KLUDGE)) == 0 ) {
  1680.     button = XP_DIALOG_BACK_BUTTON;
  1681.     } else if ( PORT_Strcasecmp(buttonString,
  1682.                   XP_GetString(XP_SEC_FINISHED)) == 0 ) {
  1683.     button = XP_DIALOG_FINISHED_BUTTON;
  1684.     } else if ( PORT_Strcasecmp(buttonString,
  1685.                   XP_GetString(XP_SEC_MOREINFO)) == 0 ) {
  1686.     button = XP_DIALOG_MOREINFO_BUTTON;
  1687.     } else {
  1688.     button = 0;
  1689.     }
  1690.  
  1691.     /* call the application handler */
  1692.     if ( state->panels[state->curPanel].handler != NULL ) {
  1693.     nextpanel = (* state->panels[state->curPanel].handler)(state, av, ac,
  1694.                                    button);
  1695.     } else {
  1696.     nextpanel = 0;
  1697.     }
  1698.  
  1699.     if ( button == XP_DIALOG_CANCEL_BUTTON ) {
  1700.     if ( state->finish ) {
  1701.         (* state->finish)(state, PR_TRUE);
  1702.     }
  1703.     goto done;
  1704.     }
  1705.     
  1706.     if ( nextpanel != 0 ) {
  1707.     state->curPanel = nextpanel - 1;
  1708.     } else {
  1709.     switch ( button ) {
  1710.       case XP_DIALOG_BACK_BUTTON:
  1711.         PORT_Assert(state->curPanel > 0);
  1712.         state->curPanel = state->curPanel - 1;
  1713.         break;
  1714.       case XP_DIALOG_NEXT_BUTTON:
  1715.         PORT_Assert(state->curPanel < ( state->panelCount - 1 ) );
  1716.         state->curPanel = state->curPanel + 1;
  1717.         break;
  1718.       case XP_DIALOG_FINISHED_BUTTON:
  1719.         if ( state->finish ) {
  1720.         (* state->finish)(state, PR_FALSE);
  1721.         }
  1722.         goto done;
  1723.     }
  1724.     }
  1725.     
  1726.     displayPanel(state);
  1727.  
  1728.     /* free arg vector */
  1729.     PORT_Free(av);
  1730.     return;
  1731.     
  1732. loser:
  1733. done:
  1734.  
  1735.     /* free arg vector */
  1736.     if ( av != NULL ) {
  1737.     PORT_Free(av);
  1738.     }
  1739.  
  1740.     if ( ( state != NULL ) && ( !state->deleted ) ) {
  1741.     /* destroy the window */
  1742.     deleteWindowCBArg *delstate;
  1743.     
  1744.     /* set callback to destroy the window */
  1745.     delstate = (deleteWindowCBArg *)PORT_Alloc(sizeof(deleteWindowCBArg));
  1746.     if ( delstate ) {
  1747.         delstate->window = (void *)state->window;
  1748.         delstate->arg = state->cbarg;
  1749.         delstate->deleteWinCallback = state->deleteCallback;
  1750.         delstate->freeArena = state->arena;
  1751.         (void)FE_SetTimeout(deleteWindow, (void *)delstate, 0);
  1752.     }
  1753.  
  1754.     state->deleted = PR_TRUE;
  1755.     }
  1756.  
  1757.     return;
  1758. }
  1759.  
  1760. /*
  1761.  * fetch a string from the dialog strings database
  1762.  */
  1763. XPDialogStrings *
  1764. XP_GetDialogStrings(int stringnum)
  1765. {
  1766.     XPDialogStrings *header = NULL;
  1767.     PRArenaPool *arena = NULL;
  1768.     char *dst, *src;
  1769.     int n, size, len, done = 0;
  1770.     
  1771.     /* get a new arena */
  1772.     arena = PORT_NewArena(XP_STRINGS_CHUNKSIZE);
  1773.     if ( arena == NULL ) {
  1774.     return(NULL);
  1775.     }
  1776.  
  1777.     /* allocate the header structure */
  1778.     header = (XPDialogStrings *)PORT_ArenaAlloc(arena, sizeof(XPDialogStrings));
  1779.     if ( header == NULL ) {
  1780.     goto loser;
  1781.     }
  1782.  
  1783.     /* init the header */
  1784.     header->arena = arena;
  1785.     header->basestringnum = stringnum;
  1786.  
  1787.     src = XP_GetString(stringnum);
  1788.     len = PORT_Strlen(src);
  1789.     size = len + 1;
  1790.     dst = header->contents =
  1791.     (char *)PORT_ArenaAlloc(arena, sizeof(char) * size);
  1792.     if (dst == NULL)
  1793.     goto loser;
  1794.     
  1795.     while (!done) {        /* Concatenate pieces to form message */
  1796.     PORT_Memcpy(dst, src, len+1);
  1797.     done = 1;
  1798.     if (XP_STRSTR(src, "%-cont-%")) { /* Continuation */
  1799.         src = XP_GetString(++stringnum);
  1800.         len = PORT_Strlen(src);
  1801.         header->contents =
  1802.         (char *)PORT_ArenaGrow(arena,
  1803.                      header->contents, size, size + len);
  1804.         if (header->contents == NULL)
  1805.         goto loser;
  1806.         dst = header->contents + size - 1;
  1807.         size += len;
  1808.         done = 0;
  1809.     }
  1810.     }
  1811.  
  1812.     /* At this point we should have the complete message in
  1813.        header->contents, including like %-cont-%, which will be
  1814.        ignored later. */
  1815.  
  1816.     /* Count the arguments in the message */
  1817.     header->nargs = -1;        /* Support %0% as lowest token */
  1818.     src = header->contents;
  1819.     while ((src = PORT_Strchr(src, '%'))) {
  1820.     src++;
  1821.     n = (int)XP_STRTOUL(src, &dst, 10);
  1822.     if (dst == src)    {    /* Integer not found... */
  1823.         src = PORT_Strchr(src, '%') + 1; /* so skip this %..% */
  1824.         PORT_Assert(NULL != src-1); /* Unclosed %..% ? */
  1825.         continue;
  1826.     }
  1827.     
  1828.     if (header->nargs < n)
  1829.         header->nargs = n;
  1830.     src = dst + 1;
  1831.     }
  1832.  
  1833.     if (++(header->nargs) > 0)  /* Allocate space for arguments */
  1834.     header->args = (char **)PORT_ArenaZAlloc(arena, sizeof(char *) *
  1835.                           header->nargs);
  1836.  
  1837.     return(header);
  1838.     
  1839. loser:
  1840.     PORT_FreeArena(arena, PR_FALSE);
  1841.     return(NULL);
  1842. }
  1843.  
  1844. /*
  1845.  * Set a dialog string to the given string.
  1846.  * The source string must be writable(not a static string), and will
  1847.  *  not be copied, so it is the responsibility of the caller to make
  1848.  *  sure it is freed after use.
  1849.  */
  1850. void
  1851. XP_SetDialogString(XPDialogStrings *strings, int argNum, char *string)
  1852. {
  1853.     /* make sure we are doing it right */
  1854.     PORT_Assert(argNum < strings->nargs);
  1855.     PORT_Assert(argNum >= 0);
  1856.     PORT_Assert(strings->args[argNum] == NULL);
  1857.     
  1858.     /* set the string */
  1859.     strings->args[argNum] = string;
  1860.     
  1861.     return;
  1862. }
  1863.  
  1864. /*
  1865.  * Copy a string to the dialog string
  1866.  */
  1867. void
  1868. XP_CopyDialogString(XPDialogStrings *strings, int argNum, const char *string)
  1869. {
  1870.     int len;
  1871.     
  1872.     /* make sure we are doing it right */
  1873.     PORT_Assert(argNum < strings->nargs);
  1874.     PORT_Assert(argNum >= 0);
  1875.     PORT_Assert(strings->args[argNum] == NULL);
  1876.     
  1877.     /* copy the string */
  1878.     len = PORT_Strlen(string) + 1;
  1879.     strings->args[argNum] = (char *)PORT_ArenaAlloc(strings->arena, len);
  1880.     if ( strings->args[argNum] != NULL ) {
  1881.     PORT_Memcpy(strings->args[argNum], string, len);
  1882.     }
  1883.     
  1884.     return;
  1885. }
  1886.  
  1887. /*
  1888.  * free the dialog strings
  1889.  */
  1890. void
  1891. XP_FreeDialogStrings(XPDialogStrings *strings)
  1892. {
  1893.     PORT_FreeArena(strings->arena, PR_FALSE);
  1894.     
  1895.     return;
  1896. }
  1897.  
  1898. static XPDialogInfo alertDialog = {
  1899.     XP_DIALOG_OK_BUTTON,
  1900.     NULL,
  1901.     600,
  1902.     224
  1903. };
  1904.  
  1905. void
  1906. XP_MakeHTMLAlert(void *proto_win, char *string)
  1907. {
  1908.     XPDialogStrings *strings;
  1909.     
  1910.     /* get empty strings */
  1911.     strings = XP_GetDialogStrings(XP_EMPTY_STRINGS);
  1912.     if ( strings == NULL ) {
  1913.     return;
  1914.     }
  1915.     
  1916.     XP_CopyDialogString(strings, 0, string);
  1917.  
  1918.     /* put up the dialog */
  1919.     XP_MakeHTMLDialog(proto_win, &alertDialog, XP_ALERT_TITLE_STRING,
  1920.               strings, NULL, PR_FALSE);
  1921.  
  1922.     return;
  1923. }
  1924.  
  1925. /*
  1926.  * destroy an HTML dialog window that has not had anything written to it yet
  1927.  */
  1928. void
  1929. XP_DestroyHTMLDialogWindow(void *window)
  1930. {
  1931.     deleteWindowCBArg *delstate;
  1932.     
  1933.     /* set callback to destroy the window */
  1934.     delstate = (deleteWindowCBArg *)PORT_Alloc(sizeof(deleteWindowCBArg));
  1935.     if ( delstate ) {
  1936.     delstate->window = window;
  1937.     delstate->arg = NULL;
  1938.     delstate->deleteWinCallback = NULL;
  1939.     delstate->freeArena = NULL;
  1940.     (void)FE_SetTimeout(deleteWindow, (void *)delstate, 0);
  1941.     }
  1942.     return;
  1943. }
  1944.  
  1945.