home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / INTERNET / WWW / LYNX / SOURCE / SRC0_8A.ZIP / DOSLYNX / SRC / HTFWRITE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-11  |  14.1 KB  |  555 lines

  1. /*        FILE WRITER                HTFWrite.h
  2. **        ===========
  3. **
  4. **    This version of the stream object just writes to a C file.
  5. **    The file is assumed open and left open.
  6. **
  7. **    Bugs:
  8. **        strings written must be less than buffer size.
  9. */
  10. #define Uses_TFileDialog
  11. #define Uses_TProgram
  12. #define Uses_TDeskTop
  13. #define Uses_TObject
  14. #include"globals.h"
  15.  
  16. //    C callable
  17. extern "C"    {
  18.  
  19. #include"capalloc.h"
  20. #include"capstdio.h"
  21. #include "HTFWriter.h"
  22.  
  23. #include "HTFormat.h"
  24. #include "HTAlert.h"
  25. #include "HTFile.h"
  26. #include<dir.h>
  27.  
  28. /*        Stream Object
  29. **        ------------
  30. */
  31.  
  32. struct _HTStream {
  33.     CONST HTStreamClass *    isa;
  34.     
  35.     FILE *            fp;
  36.     char *             end_command;
  37.     char *             remove_command;
  38.     BOOL            announce;
  39. };
  40.  
  41.  
  42. /*_________________________________________________________________________
  43. **
  44. **        B L A C K    H O L E    C L A S S
  45. **
  46. **    There is only one black hole instance shared by anyone
  47. **    who wanst a black hole.  These black holes don't radiate,
  48. **    they just absorb data.
  49. */
  50. PRIVATE void HTBlackHole_put_character ARGS2(HTStream *, me, char, c)
  51. {}
  52. PRIVATE void HTBlackHole_put_string ARGS2(HTStream *, me, CONST char*, s)
  53. {}
  54. PRIVATE void HTBlackHole_write ARGS3(HTStream *, me, CONST char*, s, int, l)
  55. {}
  56. PRIVATE void HTBlackHole_free ARGS1(HTStream *, me)
  57. {}
  58. PRIVATE void HTBlackHole_abort ARGS2(HTStream *, me, HTError, e)
  59. {}
  60.  
  61.  
  62. /*    Black Hole stream
  63. **    -----------------
  64. */
  65. PRIVATE CONST HTStreamClass HTBlackHoleClass =
  66. {        
  67.     "BlackHole",
  68.     HTBlackHole_free,
  69.     HTBlackHole_abort,
  70.     HTBlackHole_put_character,     HTBlackHole_put_string,
  71.     HTBlackHole_write
  72. }; 
  73.  
  74. PRIVATE HTStream HTBlackHoleInstance =
  75. {
  76.     &HTBlackHoleClass,
  77.     NULL,
  78.     NULL,
  79.     NULL,
  80.     NO
  81. };
  82.  
  83. /*    Black hole craetion
  84. */
  85. PUBLIC HTStream * HTBlackHole NOARGS
  86. {
  87.     return &HTBlackHoleInstance;
  88. }
  89.  
  90.  
  91. /*_________________________________________________________________________
  92. **
  93. **        F I L E     A C T I O N     R O U T I N E S
  94. **  Bug:
  95. **    All errors are ignored.
  96. */
  97.  
  98. /*    Character handling
  99. **    ------------------
  100. */
  101.  
  102. PRIVATE void HTFWriter_put_character ARGS2(HTStream *, me, char, c)
  103. {
  104.     putc(c, me->fp);
  105. }
  106.  
  107.  
  108.  
  109. /*    String handling
  110. **    ---------------
  111. **
  112. **    Strings must be smaller than this buffer size.
  113. */
  114. PRIVATE void HTFWriter_put_string ARGS2(HTStream *, me, CONST char*, s)
  115. {
  116.     fputs(s, me->fp);
  117. }
  118.  
  119.  
  120. /*    Buffer write.  Buffers can (and should!) be big.
  121. **    ------------
  122. */
  123. PRIVATE void HTFWriter_write ARGS3(HTStream *, me, CONST char*, s, int, l)
  124. {
  125.     fwrite(s, 1, l, me->fp); 
  126. }
  127.  
  128.  
  129.  
  130.  
  131. /*    Free an HTML object
  132. **    -------------------
  133. **
  134. **    Note that the SGML parsing context is freed, but the created
  135. **    object is not,
  136. **    as it takes on an existence of its own unless explicitly freed.
  137. */
  138. PRIVATE void HTFWriter_free ARGS1(HTStream *, me)
  139. {
  140.     fclose(me->fp);
  141.     if (me->end_command) {        /* Temp file */
  142.         HTProgress(me->end_command);    /* Tell user what's happening */
  143.     system(me->end_command);
  144.     free (me->end_command);
  145.     if (me->remove_command) {
  146.         system(me->remove_command);
  147.         free(me->remove_command);
  148.     }
  149.     }
  150.  
  151.     free(me);
  152. }
  153.  
  154. /*    End writing
  155. */
  156.  
  157. PRIVATE void HTFWriter_abort ARGS2(HTStream *, me, HTError, e)
  158. {
  159.     fclose(me->fp);
  160.     if (me->end_command) {        /* Temp file */
  161. #ifndef RELEASE
  162.     if (TRACE) fprintf(stderr,
  163.         "HTFWriter: Aborting: file not executed.\n");
  164. #endif /* RELEASE */
  165.     free (me->end_command);
  166.     if (me->remove_command) {
  167.         system(me->remove_command);
  168.         free(me->remove_command);
  169.     }
  170.     }
  171.  
  172.     free(me);
  173. }
  174.  
  175.  
  176.  
  177. /*    Structured Object Class
  178. **    -----------------------
  179. */
  180. PRIVATE CONST HTStreamClass HTFWriter = /* As opposed to print etc */
  181. {        
  182.     "FileWriter",
  183.     HTFWriter_free,
  184.     HTFWriter_abort,
  185.     HTFWriter_put_character,     HTFWriter_put_string,
  186.     HTFWriter_write
  187. }; 
  188.  
  189.  
  190. /*    Subclass-specific Methods
  191. **    -------------------------
  192. */
  193.  
  194. PUBLIC HTStream* HTFWriter_new ARGS1(FILE *, fp)
  195. {
  196.     HTStream* me;
  197.     
  198.     if (!fp) return NULL;
  199.  
  200.     me = (HTStream*)malloc(sizeof(*me));
  201.     if (me == NULL) outofmem(__FILE__, "HTML_new");
  202.     me->isa = &HTFWriter;       
  203.  
  204.     me->fp = fp;
  205.     me->end_command = NULL;
  206.     me->remove_command = NULL;
  207.     me->announce = NO;
  208.  
  209.     return me;
  210. }
  211.  
  212. /*    Make system command from template
  213. **    ---------------------------------
  214. **
  215. **    See mailcap spec for description of template.
  216. */
  217. /* @@ to be written.  sprintfs will do for now.  */
  218.  
  219.  
  220.  
  221. extern HTStream *HTSaveLocally(HTPresentation *HTPp_pres,
  222.     HTParentAnchor *HTPAp_anchor, HTStream *HTSp_sink)    {
  223. //    Purpose:    Prompt user for a local name to save under and return
  224. //            an open stream for WWW to write to that file.
  225. //    Arguments:    HTPp_pres    The routines used to present the
  226. //                    file to save.
  227. //            HTPAp_anchor    Not used, but is the anchor pointing
  228. //                    to this document.
  229. //            HTSp_sink    Not used, but is the stream to write
  230. //                    the presentation to.
  231. //    Return Value:    HTStream *    The opened stream for WWW to save the
  232. //                    file to.
  233. //                    It appears NULL can be returned in
  234. //                    the case of an error, but in such
  235. //                    cases we are just returning a null
  236. //                    stream so that the rest of the
  237. //                    code may continue to work.
  238. //    Remarks/Portability/Dependencies/Restrictions:
  239. //        On top of performing the normal functionality stated above,
  240. //        HTSaveLocally will have to inform the current TURLView that
  241. //        it should not try to display the URL that we are actually
  242. //        saving.
  243. //    Revision History:
  244. //        03-30-94    created
  245.  
  246.     //    First, inform the owning view that this we won't be able to
  247.     //    display this.
  248.     TURLV_current->DoNotDisplay();
  249.  
  250.     //    Secondly, check to make sure we can save locally.
  251.     //    This is taken directly from the WWW code and may not be
  252.     //    needed.
  253.     if(HTClientHost)    {
  254.         HTAlert("Can't save data to file -- please run WWW locally");
  255.         //    Return a stream that goes nowhere.
  256.         return(HTBlackHole());
  257.     }
  258.  
  259.  
  260.     //    Allocate the stream we will be returning.
  261.     auto HTStream *HTSp_me = new HTStream;
  262.     if(HTSp_me == NULL)    {
  263.         doslynxmessage("Could not allocate memory to save locally.");
  264.         //    Attempt to keep running by returning a black hole.
  265.         return(HTBlackHole());
  266.     }
  267.     //    Fill up a few members right now.
  268.     //    Use action routines of the HTFWriter.
  269.     //    No command to execute at the end.
  270.     //    No remove command to delete the file, will keep.
  271.     //    Announce??
  272.     HTSp_me->isa = &HTFWriter;
  273.     HTSp_me->end_command = NULL;
  274.     HTSp_me->remove_command = NULL;
  275.     HTSp_me->announce = YES;
  276.  
  277.     //    Create a file dialog to ask the user for a file name in which
  278.     //    to save in.  But hey, let's also get the filename to suggest.
  279.     auto char *cp_suggest;
  280.     if(HTPAp_anchor->address != NULL)    {
  281.         cp_suggest = strrchr(HTPAp_anchor->address, '/');
  282.         if(cp_suggest == NULL)    {
  283.             cp_suggest = newStr("*.*");
  284.         }
  285.         else    {
  286.             cp_suggest = newStr(cp_suggest + 1);
  287.         }
  288.     }
  289.     else    {
  290.         cp_suggest = newStr("*.*");
  291.     }
  292.  
  293.     auto TFileDialog *TFD = new TFileDialog(cp_suggest, HTPAp_anchor->
  294.             address, "Save as", fdOKButton, usi_SaveHist);
  295.  
  296.     //    If the dialog was not allocated
  297.     if(TFD == NULL)    {
  298.         doslynxmessage("Could not allocate memory to save locally.");
  299.         //    Keep running by returning the black hole.
  300.         return(HTBlackHole());
  301.     }
  302.  
  303.     //    Execute the dialog.
  304.     auto unsigned short int usi_retval = TProgram::deskTop->execView(TFD);
  305.  
  306.     //    If the user didn't cancel.
  307.     if(usi_retval == cmCancel)    {
  308.         TObject::destroy(TFD);
  309.         //    Return the black hole to save in, user doesn't want
  310.         //    it.
  311.         return(HTBlackHole());
  312.     }
  313.  
  314.     //    Small buffer to hold file name
  315.     auto char ca_buffer[usi_TILURLSize];
  316.  
  317.     //    Get the information from the Dialog
  318.     TFD->getFileName(ca_buffer);
  319.  
  320.     //    Done with the dialog.
  321.     TObject::destroy(TFD);
  322.     //    Destroy the suggested name.
  323.     delete(cp_suggest);
  324.  
  325.     //    Open the stream's file.
  326.     HTSp_me->fp = fopen(ca_buffer, "wb");
  327.     if(HTSp_me->fp == NULL)    {
  328.         doslynxmessage("Unable to open local file " << ca_buffer
  329.             << " for writing.");
  330.         //    Return the black hole.
  331.         return(HTBlackHole());
  332.     }
  333.  
  334.     //    Done, return the allocated stream.
  335.     return(HTSp_me);
  336. }
  337.  
  338.  
  339. extern HTStream *HTHandleImage(HTPresentation *HTPp_pres,
  340.     HTParentAnchor *HTPAp_anchor, HTStream *HTSp_sink)    {
  341. //    Purpose:    Prompt user for a local name to save under and return
  342. //            an open stream for WWW to write to that file.  Also,
  343. //            inform the owning view that this is a viewable image.
  344. //    Arguments:    HTPp_pres    The routines used to present the
  345. //                    file to save.
  346. //            HTPAp_anchor    Not used, but is the anchor pointing
  347. //                    to this document.
  348. //            HTSp_sink    Not used, but is the stream to write
  349. //                    the presentation to.
  350. //    Return Value:    HTStream *    The opened stream for WWW to save the
  351. //                    file to.
  352. //                    It appears NULL can be returned in
  353. //                    the case of an error, but in such
  354. //                    cases we are just returning a null
  355. //                    stream so that the rest of the
  356. //                    code may continue to work.
  357. //    Remarks/Portability/Dependencies/Restrictions:
  358. //        On top of performing the normal functionality stated above,
  359. //        HTHandleImage will have to inform the current TURLView that
  360. //        it should not try to display the URL that we are actually
  361. //        saving.  Also, we will inform the owning view that this is
  362. //        a viewable image, so that once the load is accomplished, to
  363. //        display.
  364. //    Revision History:
  365. //        03-30-94    created
  366. //        04-06-94    Converted for images.
  367.  
  368.     //    First, inform the owning view that this we won't be able to
  369.     //    display this.
  370.     TURLV_current->DoNotDisplay();
  371.  
  372.     //    Secondly, check to make sure we can save locally.
  373.     //    This is taken directly from the WWW code and may not be
  374.     //    needed.
  375.     if(HTClientHost)    {
  376.         HTAlert("Can't save data to file -- please run WWW locally");
  377.         //    Return a stream that goes nowhere.
  378.         return(HTBlackHole());
  379.     }
  380.  
  381.  
  382.     //    Allocate the stream we will be returning.
  383.     auto HTStream *HTSp_me = new HTStream;
  384.     if(HTSp_me == NULL)    {
  385.         doslynxmessage("Could not allocate memory to save locally.");
  386.         //    Attempt to keep running by returning a black hole.
  387.         return(HTBlackHole());
  388.     }
  389.     //    Fill up a few members right now.
  390.     //    Use action routines of the HTFWriter.
  391.     //    No command to execute at the end.
  392.     //    No remove command to delete the file, will keep.
  393.     //    Announce??
  394.     HTSp_me->isa = &HTFWriter;
  395.     HTSp_me->end_command = NULL;
  396.     HTSp_me->remove_command = NULL;
  397.     HTSp_me->announce = YES;
  398.  
  399.     //    Create a file dialog to ask the user for a file name in which
  400.     //    to save in.  But hey, let's also get the filename to suggest.
  401.     auto char *cp_suggest;
  402.     if(HTPAp_anchor->address != NULL)    {
  403.         cp_suggest = strrchr(HTPAp_anchor->address, '/');
  404.         if(cp_suggest == NULL)    {
  405.             cp_suggest = newStr("*.gif");
  406.         }
  407.         else    {
  408.             cp_suggest = newStr(cp_suggest + 1);
  409.         }
  410.     }
  411.     else    {
  412.         cp_suggest = newStr("*.gif");
  413.     }
  414.  
  415.     auto TFileDialog *TFD = new TFileDialog(cp_suggest, HTPAp_anchor->
  416.         address, "Save image as", fdOKButton, usi_SaveHist);
  417.  
  418.     //    If the dialog was not allocated
  419.     if(TFD == NULL)    {
  420.         doslynxmessage("Could not allocate memory to save locally.");
  421.         //    Keep running by returning the black hole.
  422.         return(HTBlackHole());
  423.     }
  424.  
  425.     //    Execute the dialog.
  426.     auto unsigned short int usi_retval = TProgram::deskTop->execView(TFD);
  427.  
  428.     //    If the user didn't cancel.
  429.     if(usi_retval == cmCancel)    {
  430.         TObject::destroy(TFD);
  431.         //    Return the black hole to save in, user doesn't want
  432.         //    it.
  433.         return(HTBlackHole());
  434.     }
  435.  
  436.     //    Small buffer to hold file name
  437.     auto char ca_buffer[usi_TILURLSize];
  438.  
  439.     //    Get the information from the Dialog
  440.     TFD->getFileName(ca_buffer);
  441.  
  442.     //    Done with the dialog.
  443.     TObject::destroy(TFD);
  444.     //    Done with the suggested filename.
  445.     delete(cp_suggest);
  446.  
  447.     //    Open the stream's file.
  448.     HTSp_me->fp = fopen(ca_buffer, "wb");
  449.     if(HTSp_me->fp == NULL)    {
  450.         doslynxmessage("Unable to open local file " << ca_buffer
  451.             << " for writing.");
  452.         //    Return the black hole.
  453.         return(HTBlackHole());
  454.     }
  455.  
  456.     //    Here we can inform the owning window that this is an image.
  457.     //    Pass the file name so that the view can take action upon it.
  458.     TURLV_current->isImage(ca_buffer);
  459.  
  460.     //    Done, return the allocated stream.
  461.     return(HTSp_me);
  462. }
  463.  
  464.  
  465.  
  466.  
  467. /*    Take action using a system command
  468. **    ----------------------------------
  469. **
  470. **    originally from Ghostview handling by Marc Andreseen.
  471. **    Creates temporary file, writes to it, executes system command
  472. **    on end-document.  The suffix of the temp file can be given
  473. **    in case the application is fussy, or so that a generic opener can
  474. **    be used.
  475. */
  476. PUBLIC HTStream* HTSaveAndExecute ARGS3(
  477.     HTPresentation *,    pres,
  478.     HTParentAnchor *,    anchor,    /* Not used */
  479.     HTStream *,        sink)    /* Not used */
  480.  
  481. #ifdef unix
  482. #define REMOVE_COMMAND "/bin/rm -f %s\n"
  483. #endif
  484. #ifdef VMS
  485. #define REMOVE_COMMAND "delete/noconfirm/nolog %s.."
  486. #endif
  487.  
  488. #ifdef REMOVE_COMMAND
  489. {
  490.     char *fnam;
  491.     CONST char * suffix;
  492.     
  493.     HTStream* me;
  494.     
  495.     if (HTClientHost) {
  496.         HTAlert("Can't save data to file -- please run WWW locally");
  497.     return HTBlackHole();
  498.     }
  499.  
  500.     me = (HTStream*)malloc(sizeof(*me));
  501.     if (me == NULL) outofmem(__FILE__, "Save and execute");
  502.     me->isa = &HTFWriter;  
  503.     
  504.     /* Save the file under a suitably suffixed name */
  505.     
  506.     suffix = HTFileSuffix(pres->rep);
  507.  
  508.     fnam = (char *)malloc (L_tmpnam + 16 + strlen(suffix));
  509.     tmpnam (fnam);
  510.     if (suffix) strcat(fnam, suffix);
  511.     
  512.     me->fp = fopen (fnam, "w");
  513.     if (!me->fp) {
  514.     HTAlert("Can't open temporary file!");
  515.         free(fnam);
  516.     free(me);
  517.     return NULL;
  518.     }
  519.  
  520. /*    Make command to process file
  521. */
  522.     me->end_command = (char *)malloc (
  523.                 (strlen (pres->command) + 10+ 3*strlen(fnam))
  524.                  * sizeof (char));
  525.     if (me == NULL) outofmem(__FILE__, "SaveAndExecute");
  526.     
  527.     sprintf (me->end_command, pres->command, fnam, fnam, fnam);
  528.  
  529.     me->remove_command = NULL;    /* If needed, put into end_command */
  530. #ifdef NOPE
  531. /*    Make command to delete file
  532. */ 
  533.     me->remove_command = (char *)malloc (
  534.                 (strlen (REMOVE_COMMAND) + 10+ strlen(fnam))
  535.                  * sizeof (char));
  536.     if (me == NULL) outofmem(__FILE__, "SaveAndExecute");
  537.     
  538.     sprintf (me->remove_command, REMOVE_COMMAND, fnam);
  539. #endif
  540.  
  541.     me->announce = NO;
  542.     free (fnam);
  543.     return me;
  544. }
  545.  
  546. #else    /* can do remove */
  547. { return NULL; }
  548. #endif
  549.  
  550.  
  551. /*    Format Converter using system command
  552. **    -------------------------------------
  553. */
  554.  
  555. }; // extern "C"