home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / mailattach.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  29.7 KB  |  999 lines

  1. /* -*- Mode: C; tab-width: 8; 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.    mailattach.c --- Mail Attachment stuff goes here.
  20.    Created: Dora Hsu<dora@netscape.com>, 6-May-96.
  21.  */
  22.  
  23.  
  24. #include "mozilla.h"
  25. #include "xfe.h"
  26. #include <Xfe/XfeP.h> /* for _XfeHeight() */
  27. /* for XP_GetString() */
  28. #include <xpgetstr.h>
  29. #include "felocale.h"
  30.  
  31.  
  32. extern int XFE_INVALID_FILE_ATTACHMENT_IS_A_DIRECTORY;
  33. extern int XFE_INVALID_FILE_ATTACHMENT_NOT_READABLE;
  34. extern int XFE_INVALID_FILE_ATTACHMENT_DOESNT_EXIST;
  35.  
  36. extern int XFE_DLG_OK;
  37. extern int XFE_DLG_CLEAR;
  38. extern int XFE_DLG_CANCEL;
  39.  
  40. static char* fe_last_attach_type = NULL;
  41.  
  42. static void
  43. fe_attachmentUpdate(struct fe_mail_attach_data* mad )
  44. {
  45.   const char* ptr;
  46.   char *str = NULL;
  47.  
  48.   if ( mad && mad->comppane )
  49.   {
  50.   mad->attachments[mad->nattachments].url = NULL;
  51.   MSG_SetAttachmentList(mad->comppane, mad->attachments);
  52.   ptr = MSG_GetCompHeader(mad->comppane, MSG_ATTACHMENTS_HEADER_MASK);
  53.   
  54.   if (ptr)
  55.   {
  56.     str = malloc(sizeof(char)*(strlen(ptr)+1));
  57.     strcpy(str, ptr);
  58.   }
  59.  
  60.   if (str) free(str);
  61.   }
  62. }
  63.  
  64.  
  65. static void
  66. fe_del_attachment(struct fe_mail_attach_data* mad, int pos)
  67. {
  68.   if (pos > mad->nattachments) return;
  69.   else XP_ASSERT(pos <= mad->nattachments);
  70.  
  71.   pos--;
  72.   if (mad->attachments[pos].url)
  73.     XP_FREE((char *)mad->attachments[pos].url);
  74.   pos++;
  75.   while (pos < mad->nattachments) {
  76.     mad->attachments[pos-1] = mad->attachments[pos];
  77.     pos++;
  78.   }
  79.   mad->nattachments--;
  80.   fe_attachmentUpdate(mad);
  81. }
  82.  
  83. static void
  84. fe_add_attachmentData(struct fe_mail_attach_data *mad,
  85.             const struct MSG_AttachmentData *data)
  86. {
  87.   struct MSG_AttachmentData *m;
  88.   char *name = (char *)data->url;
  89.   XmString xmstr;
  90.  
  91.   if (!name || !*name) return;
  92.  
  93.   if (mad->nattachments >= XFE_MAX_ATTACHMENTS) return;
  94.   else XP_ASSERT(mad->nattachments < XFE_MAX_ATTACHMENTS);
  95.  
  96.   xmstr = XmStringCreate(name, XmSTRING_DEFAULT_CHARSET);
  97.   XmListAddItem(mad->list, xmstr, 0);
  98.  
  99.   m = &mad->attachments[mad->nattachments];
  100.   *m = *data;
  101.   m->url = XP_STRDUP(data->url);
  102.  
  103.   mad->nattachments++;
  104.   if (mad->nattachments == 1)
  105.     XmListSelectPos(mad->list, 1, True);
  106.  
  107.   XmListSelectItem(mad->list, xmstr, TRUE);
  108.   XmStringFree(xmstr);
  109. }
  110.  
  111.  
  112. static void
  113. fe_add_attachment(struct fe_mail_attach_data *mad, char *name)
  114. {
  115.   struct MSG_AttachmentData m = {0};
  116.   Boolean b;
  117.   XmString xmstr;
  118.  
  119.   if (!name || !*name) return;
  120.  
  121.   if(mad->nattachments >= XFE_MAX_ATTACHMENTS) return;
  122.   else XP_ASSERT(mad->nattachments < XFE_MAX_ATTACHMENTS);
  123.  
  124.   xmstr = XmStringCreate(name, XmSTRING_DEFAULT_CHARSET);
  125.   XmListAddItem(mad->list, xmstr, 0);
  126.  
  127.   XtVaGetValues (mad->text_p, XmNset, &b, 0);
  128.   if (b)
  129.     m.desired_type = TEXT_PLAIN;
  130.   else {
  131.     XtVaGetValues (mad->postscript_p, XmNset, &b, 0);
  132.     if (b)
  133.       m.desired_type = APPLICATION_POSTSCRIPT;
  134.   }
  135.   m.url = name;
  136.  
  137.   mad->attachments[mad->nattachments] = m;
  138.   mad->nattachments++;
  139.   fe_attachmentUpdate(mad);
  140.  
  141.   XmListSelectItem(mad->list, xmstr, TRUE);
  142.   XmStringFree(xmstr);
  143. }
  144. /***********************************
  145.  * Location popup related routines *
  146.  ***********************************/
  147.  
  148. static void
  149. fe_locationOk_cb (Widget widget, XtPointer closure, XtPointer call_data)
  150. {
  151.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  152.   char *url = fe_GetTextField(mad->location_text);
  153.  
  154.   if (url && *url)
  155.     fe_add_attachment(mad, url);
  156.   else
  157.     if (url) XtFree(url);
  158.   XtUnmanageChild(mad->location_shell);
  159. }
  160. static void
  161. fe_locationClear_cb (Widget widget, XtPointer closure, XtPointer call_data)
  162. {
  163.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  164.   fe_SetTextField (mad->location_text, "");
  165.   /* Focus on the text widget after this, since otherwise you have to
  166.      click again. */
  167.   XmProcessTraversal (mad->location_text, XmTRAVERSE_CURRENT);
  168. }
  169.  
  170. static void
  171. fe_locationCancel_cb (Widget widget, XtPointer closure, XtPointer call_data)
  172. {
  173.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  174.   XtUnmanageChild(mad->location_shell);
  175. }
  176.  
  177. static void
  178. fe_attach_make_location(struct fe_mail_attach_data *mad)
  179. {
  180.   Arg av [20];
  181.   int ac;
  182.   Visual *v = 0;
  183.   Colormap cmap = 0;
  184.   Cardinal depth = 0;
  185.  
  186.   Widget shell;
  187.   Widget parent;
  188.   Widget form;
  189.   Widget label, location_label, location_text;
  190.   Widget ok_button, clear_button, cancel_button;
  191.  
  192.   Widget kids [20];
  193.   int i;
  194.  
  195.   if (mad->location_shell) return;
  196.  
  197. #ifdef dp_DEBUG
  198.   fprintf(stderr, "Making attach_location widgets : fe_attach_make_location().\n");
  199. #endif
  200.  
  201.   parent = CONTEXT_WIDGET(mad->context);
  202.  
  203.   XtVaGetValues (parent, XtNvisual, &v, XtNcolormap, &cmap,
  204.          XtNdepth, &depth, 0);
  205.  
  206.   ac = 0;
  207.   XtSetArg (av[ac], XmNvisual, v); ac++;
  208.   XtSetArg (av[ac], XmNdepth, depth); ac++;
  209.   XtSetArg (av[ac], XmNcolormap, cmap); ac++;
  210. /*  XtSetArg (av[ac], XmNallowShellResize, True); ac++; */
  211. /*  XtSetArg (av[ac], XmNtransientFor, parent); ac++; */
  212.   XtSetArg (av[ac], XmNautoUnmanage, False); ac++;
  213.   XtSetArg (av[ac], XmNdeleteResponse, XmUNMAP); ac++;
  214.   XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_MODELESS); ac++;
  215.   shell = XmCreateTemplateDialog (parent, "location_popup", av, ac);
  216.  
  217.   fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_OK_BUTTON));
  218.   fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_CANCEL_BUTTON));
  219.   fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_DEFAULT_BUTTON));
  220.   fe_UnmanageChild_safe (XmMessageBoxGetChild (shell, XmDIALOG_HELP_BUTTON));
  221.  
  222.   ac = 0;
  223.   ok_button = XmCreatePushButtonGadget (shell,
  224.                                         XP_GetString(XFE_DLG_OK),
  225.                                         av, ac);
  226.   clear_button = XmCreatePushButtonGadget (shell, 
  227.                                            XP_GetString(XFE_DLG_CLEAR), 
  228.                                            av, ac);
  229.   cancel_button = XmCreatePushButtonGadget (shell, 
  230.                                             XP_GetString(XFE_DLG_CANCEL),
  231.                                                          av, ac);
  232.  
  233.   ac = 0;
  234.   form = XmCreateForm(shell, "form", av, ac);
  235.   label = XmCreateLabelGadget( form, "label", av, ac);
  236.   location_label = XmCreateLabelGadget( form, "locationLabel", av, ac);
  237.   location_text = fe_CreateTextField( form, "locationText", av, ac);
  238.  
  239.   if (fe_globalData.nonterminal_text_translations)
  240.     XtOverrideTranslations (location_text, fe_globalData.
  241.                 nonterminal_text_translations);
  242.  
  243.   XtVaSetValues (label,
  244.          XmNtopAttachment, XmATTACH_FORM,
  245.          XmNbottomAttachment, XmATTACH_NONE,
  246.          XmNleftAttachment, XmATTACH_FORM,
  247.          XmNrightAttachment, XmATTACH_FORM,
  248.          0);
  249.   XtVaSetValues (location_label,
  250.          XmNtopAttachment, XmATTACH_WIDGET,
  251.          XmNtopWidget, label,
  252.          XmNbottomAttachment, XmATTACH_NONE,
  253.          XmNleftAttachment, XmATTACH_FORM,
  254.          XmNrightAttachment, XmATTACH_NONE,
  255.          0);
  256.   XtVaSetValues (location_text,
  257.          XmNtopAttachment, XmATTACH_WIDGET,
  258.          XmNtopWidget, label,
  259.          XmNbottomAttachment, XmATTACH_NONE,
  260.          XmNleftAttachment, XmATTACH_WIDGET,
  261.          XmNleftWidget, location_label,
  262.          XmNrightAttachment, XmATTACH_FORM,
  263.          0);
  264.  
  265.   _XfeHeight(location_label) = _XfeHeight(location_text);
  266.  
  267.   XtAddCallback(ok_button, XmNactivateCallback, fe_locationOk_cb, mad);
  268.   XtAddCallback(clear_button, XmNactivateCallback, fe_locationClear_cb, mad);
  269.   XtAddCallback(cancel_button, XmNactivateCallback, fe_locationCancel_cb, mad);
  270.  
  271.   fe_HackDialogTranslations (form);
  272.  
  273.   mad->location_shell = shell;
  274.   i = 0;
  275.   kids[i++] = mad->location_text = location_text;
  276.   kids[i++] = location_label;
  277.   kids[i++] = label;
  278.   XtManageChildren(kids, i);
  279.   i = 0;
  280.   kids[i++] = ok_button;
  281.   kids[i++] = clear_button;
  282.   kids[i++] = cancel_button;
  283.   XtManageChildren(kids, i);
  284.  
  285.   XtManageChild(form);
  286.   XtManageChild(shell);
  287. }
  288.  
  289. /*************************
  290.  * File Attachment popup *
  291.  *************************/
  292. static void 
  293. fe_attachFile_cb (Widget widget, XtPointer closure, XtPointer call_data)
  294. {
  295.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data *) closure;
  296.   XmFileSelectionBoxCallbackStruct *sbc =
  297.     (XmFileSelectionBoxCallbackStruct *) call_data;
  298.   char *file;
  299.   char *msg;
  300.  
  301.   switch (sbc->reason) {
  302.     case XmCR_NO_MATCH:
  303.     XBell (XtDisplay (widget), 0);
  304.     break;
  305.  
  306.     case XmCR_OK:
  307.     XmStringGetLtoR (sbc->value, XmSTRING_DEFAULT_CHARSET, &file);
  308.     if (!fe_isFileExist(file)) {
  309.         msg = PR_smprintf( XP_GetString( XFE_INVALID_FILE_ATTACHMENT_DOESNT_EXIST ), file);
  310.         if (msg) {
  311.         fe_Alert_2(XtParent(mad->file_shell), msg);
  312.         XP_FREE(msg);
  313.         }
  314.     }
  315.     else if (!fe_isFileReadable(file)) {
  316.         msg = PR_smprintf( XP_GetString( XFE_INVALID_FILE_ATTACHMENT_NOT_READABLE ) , file);
  317.         if (msg) {
  318.         fe_Alert_2(XtParent(mad->file_shell), msg);
  319.         XP_FREE(msg);
  320.         }
  321.     }
  322.     else if (fe_isDir(file)) {
  323.         msg = PR_smprintf( XP_GetString( XFE_INVALID_FILE_ATTACHMENT_IS_A_DIRECTORY ), file);
  324.         if (msg) {
  325.         fe_Alert_2(XtParent(mad->file_shell), msg);
  326.         if (msg) XP_FREE(msg);
  327.         }
  328.     }
  329.     else {
  330.       fe_add_attachment(mad, file);
  331.       XtUnmanageChild(mad->file_shell);
  332.     }
  333.     break;
  334.  
  335.     case XmCR_CANCEL:
  336.     XtUnmanageChild(mad->file_shell);
  337.     break;
  338.     default:
  339.       abort ();
  340.   }
  341. }
  342.  
  343. static void
  344. fe_attach_make_file(struct fe_mail_attach_data *mad)
  345. {
  346.   char *text = 0;
  347.   XmString xmpat, xmfile;
  348.   char buf [1024];
  349.   Arg av [20];
  350.   int ac;
  351.   Visual *v = 0;
  352.   Colormap cmap = 0;
  353.   Cardinal depth = 0;
  354.   Widget shell;
  355.   Widget parent;
  356.   Widget fileb;
  357.   Boolean dirp = False;
  358.  
  359.   if (mad->file_shell) return;
  360.  
  361. #ifdef dp_DEBUG
  362.   fprintf(stderr, "Making attach_file widgets : fe_attach_make_file().\n");
  363. #endif
  364.  
  365.   parent = CONTEXT_WIDGET (mad->context);
  366.  
  367.   XtVaGetValues (parent, XtNvisual, &v, XtNcolormap, &cmap,
  368.          XtNdepth, &depth, 0);
  369. /***
  370.   text = fe_GetTextField(text_field);
  371.   text = fe_StringTrim (text);
  372. ***/
  373.  
  374.   if (!text || !*text) {
  375.     xmpat = 0;
  376.     xmfile = 0;
  377.   }
  378.   else if (dirp) {
  379.     if (text [strlen (text) - 1] == '/')
  380.     text [strlen (text) - 1] = 0;
  381.     PR_snprintf (buf, sizeof (buf), "%.900s/*", text);
  382.     xmpat = XmStringCreateLtoR (buf, XmSTRING_DEFAULT_CHARSET);
  383.     xmfile = XmStringCreateLtoR (text, XmSTRING_DEFAULT_CHARSET);
  384.   }
  385.   else {
  386.     char *f;
  387.     if (text [strlen (text) - 1] == '/')
  388.       PR_snprintf (buf, sizeof (buf), "%.900s/*", text);
  389.     else
  390.       PR_snprintf (buf, sizeof (buf), "%.900s", text);
  391.     xmfile = XmStringCreateLtoR (buf, XmSTRING_DEFAULT_CHARSET);
  392.     f = strrchr (text, '/');
  393.     if (f && f != text)
  394.       *f = 0;
  395.     PR_snprintf (buf, sizeof (buf), "%.900s/*", text);
  396.     xmpat = XmStringCreateLtoR (buf, XmSTRING_DEFAULT_CHARSET);
  397.   }
  398.   if (text) free (text);
  399.  
  400.   ac = 0;
  401.   XtSetArg (av[ac], XmNvisual, v); ac++;
  402.   XtSetArg (av[ac], XmNdepth, depth); ac++;
  403.   XtSetArg (av[ac], XmNcolormap, cmap); ac++;
  404. /*  XtSetArg (av[ac], XmNallowShellResize, True); ac++;*/
  405.   XtSetArg (av[ac], XmNdeleteResponse, XmUNMAP); ac++;
  406.   XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_MODELESS); ac++;
  407.   shell = XmCreateDialogShell (parent, "fileBrowser_popup", av, ac);
  408.  
  409.   ac = 0;
  410.   XtSetArg (av[ac], XmNfileTypeMask,
  411.         (dirp ? XmFILE_DIRECTORY : XmFILE_REGULAR)); ac++;
  412.   fileb = XmCreateFileSelectionBox (shell, "fileBrowser", av, ac);
  413. #ifdef NO_HELP
  414.   fe_UnmanageChild_safe (XmSelectionBoxGetChild (fileb, XmDIALOG_HELP_BUTTON));
  415. #endif
  416.  
  417.   if (xmpat) {
  418.     XtVaSetValues (fileb, XmNdirMask, xmpat, 0);
  419.     XtVaSetValues (fileb, XmNpattern, xmpat, 0);
  420.     XmFileSelectionDoSearch (fileb, xmpat);
  421.     XtVaSetValues (fileb, XmNdirSpec, xmfile, 0);
  422.     XmStringFree (xmpat);
  423.     XmStringFree (xmfile);
  424.   }
  425.  
  426.   XtAddCallback(fileb, XmNnoMatchCallback, fe_attachFile_cb, mad);
  427.   XtAddCallback(fileb, XmNokCallback,      fe_attachFile_cb, mad);
  428.   XtAddCallback(fileb, XmNcancelCallback,  fe_attachFile_cb, mad);
  429.  
  430.   mad->file_shell = fileb;
  431.  
  432.   fe_HackDialogTranslations (fileb);
  433.  
  434.   fe_NukeBackingStore (fileb);
  435.   XtManageChild (fileb);
  436. }
  437.  
  438. static void
  439. fe_attach_doc_type_cb (Widget widget, XtPointer closure, XtPointer call_data)
  440. {
  441.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  442.   int *poslist, npos;
  443.   int attach_pos = -1;
  444.  
  445.   if (XmListGetSelectedPos(mad->list, &poslist, &npos)) {
  446.     attach_pos = poslist[npos - 1] - 1;
  447.     XP_FREE(poslist);
  448.   }
  449.  
  450.   /*
  451.    * my how intuitive, if the file is attach as siurce, desired type = NULL.
  452.    */
  453.   XtVaSetValues (widget, XmNset, True, 0);
  454.   if (widget == mad->text_p) {
  455.     XtVaSetValues (mad->source_p, XmNset, False, 0);
  456.     XtVaSetValues (mad->postscript_p, XmNset, False, 0);
  457.     if (attach_pos >= 0)
  458.       mad->attachments[attach_pos].desired_type = TEXT_PLAIN;
  459.   }
  460.   else if (widget == mad->source_p) {
  461.     XtVaSetValues (mad->text_p, XmNset, False, 0);
  462.     XtVaSetValues (mad->postscript_p, XmNset, False, 0);
  463.     if (attach_pos >= 0)
  464.       mad->attachments[attach_pos].desired_type = NULL;
  465.   }
  466.   else if (widget == mad->postscript_p) {
  467.     XtVaSetValues (mad->source_p, XmNset, False, 0);
  468.     XtVaSetValues (mad->text_p, XmNset, False, 0);
  469.     if (attach_pos >= 0)
  470.       mad->attachments[attach_pos].desired_type = APPLICATION_POSTSCRIPT;
  471.   }
  472.   else
  473.     abort ();
  474. }
  475.  
  476. #if 0
  477. static void
  478. fe_attachDestroy_cb (Widget widget, XtPointer closure, XtPointer call_data)
  479. {
  480.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  481.   int i;
  482.  
  483. #ifdef dp_DEBUG
  484.   fprintf(stderr, "fe_attachDestroy_cb()\n");
  485.   fprintf(stderr, "Destroying fe_mail_attach_data...\n");
  486. #endif
  487.  
  488.   /* Free the list of attachments too */
  489.   for(i=0; i<mad->nattachments; i++) {
  490.     XP_FREE((char *)mad->attachments[i].url);
  491.   }
  492.   if (mad->location_shell)
  493.     XtDestroyWidget(mad->location_shell);
  494.   if (mad->file_shell)
  495.     XtDestroyWidget(XtParent(mad->file_shell));
  496. /* This should be an error ** CONTEXT_DATA(mad->context) ->mad = NULL; */
  497.   free (mad);
  498. }
  499. #endif
  500.  
  501. #if 0
  502. static void
  503. fe_attachCancel_cb (Widget widget, XtPointer closure, XtPointer call_data)
  504. {
  505.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  506.  
  507.   /* We dont need to delete all the attachments that we have as they will
  508.      be deleted either the next time we show the attach window (or) when
  509.      the message composition context gets destroyed */
  510.  
  511.   XtUnmanageChild(mad->shell);
  512.   if (mad->location_shell)
  513.     XtUnmanageChild(mad->location_shell);
  514.   if (mad->file_shell)
  515.     XtUnmanageChild(mad->file_shell);
  516. }
  517. #endif
  518.  
  519. #if 0
  520. static void
  521. fe_attachOk_cb (Widget widget, XtPointer closure, XtPointer call_data)
  522. {
  523.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  524.   const char* ptr;
  525.   char *str = NULL;
  526.  
  527.   mad->attachments[mad->nattachments].url = NULL;
  528.   MSG_SetAttachmentList(mad->comppane, mad->attachments);
  529.   ptr = MSG_GetCompHeader(mad->comppane, MSG_ATTACHMENTS_HEADER_MASK);
  530.  
  531.   if ( ptr )
  532.   {
  533.   str = malloc(sizeof(char)*(strlen(ptr)+1));
  534.   strcpy(str, ptr);
  535.   }
  536.  
  537.   if (str) free(str);
  538.  
  539.   /* We dont need to delete all the attachments that we have as they will
  540.      be deleted either the next time we show the attach window (or) when
  541.      the message composition context gets destroyed */
  542.  
  543.   XtUnmanageChild(mad->shell);
  544.   if (mad->location_shell)
  545.     XtUnmanageChild(mad->location_shell);
  546.   if (mad->file_shell)
  547.     XtUnmanageChild(mad->file_shell);
  548. }
  549. #endif
  550.  
  551. static void
  552. fe_attach_location_cb (Widget widget, XtPointer closure, XtPointer call_data)
  553. {
  554.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  555.  
  556.   if (!mad->location_shell) fe_attach_make_location(mad);
  557.  
  558.   XtManageChild(mad->location_shell);
  559.   XMapRaised(XtDisplay(mad->location_shell), XtWindow(mad->location_shell));
  560. }
  561.  
  562. static void
  563. fe_attach_file_cb (Widget widget, XtPointer closure, XtPointer call_data)
  564. {
  565.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  566.  
  567.   if (!mad->file_shell) fe_attach_make_file(mad);
  568.  
  569.   XtManageChild(mad->file_shell);
  570.   XMapRaised(XtDisplay(mad->file_shell), XtWindow(mad->file_shell));
  571. }
  572.  
  573. static void
  574. fe_attach_delete_cb (Widget widget, XtPointer closure, XtPointer call_data)
  575. {
  576.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  577.   int *poslist, npos;
  578.   int i, pos;
  579.  
  580.   if (XmListGetSelectedPos(mad->list, &poslist, &npos)) {
  581.     for(i=0; i<npos; i++) {
  582.       XmListDeletePos(mad->list, poslist[i]);
  583.       fe_del_attachment(mad, poslist[i]);
  584.     }
  585.     /*
  586.      * After deleting an item from the list, select the
  587.      * previous item in the list (or the last if it was
  588.      * the first.)
  589.      */
  590.     pos = poslist[npos - 1] - 1;
  591.     if (pos < 0)
  592.       pos = 0;
  593.     XmListSelectPos(mad->list, pos, TRUE);
  594.     XP_FREE(poslist);
  595.   }
  596.  
  597.   /*
  598.    * If nothing left in the list selected, desensitize
  599.    * the delete button.
  600.    */
  601.   if (!XmListGetSelectedPos(mad->list, &poslist, &npos)) {
  602.     XtVaSetValues(mad->delete_attach, XmNsensitive, False, 0);
  603.   }
  604.   else XP_FREE(poslist);
  605. }
  606.  
  607. static void
  608. fe_attach_select_cb (Widget widget, XtPointer closure, XtPointer call_data)
  609. {
  610.   struct fe_mail_attach_data *mad = (struct fe_mail_attach_data  *) closure;
  611.   XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
  612.   const char *s;
  613.   Widget which_w = 0;
  614.  
  615.   if (cbs->item_position > mad->nattachments) return;
  616.   else XP_ASSERT(cbs->item_position <= mad->nattachments);
  617.  
  618.   s = mad->attachments[cbs->item_position-1].desired_type;
  619.  
  620.   if (!s || !*s)
  621.     which_w = mad->source_p;
  622.   else if (!XP_STRCMP(s, APPLICATION_POSTSCRIPT))
  623.     which_w = mad->postscript_p;
  624.   else if (!XP_STRCMP(s, TEXT_PLAIN))
  625.     which_w = mad->text_p;
  626.  
  627.   if (which_w == 0) return;
  628.   else XP_ASSERT (which_w != 0);
  629.   fe_attach_doc_type_cb(which_w, (XtPointer)mad, (XtPointer)NULL);
  630.  
  631.   XtVaSetValues(mad->delete_attach, XmNsensitive, True, 0);
  632. }
  633.  
  634. void
  635. fe_make_new_attach_list (MWContext *context)
  636. {
  637.   fe_ContextData* data = CONTEXT_DATA(context);
  638.   struct fe_mail_attach_data *mad = data->mad;
  639.   const struct MSG_AttachmentData *list;
  640.   int i;
  641.  
  642.   /* Free the existing list of attachments */
  643.   XmListDeleteAllItems(mad->list);
  644.   for(i=0; i<mad->nattachments; i++) {
  645.     XP_FREE((char *)mad->attachments[i].url);
  646.   }
  647.   mad->comppane = data->comppane;
  648.   mad->nattachments = 0;
  649.     
  650.   /* Refresh the list of attachments */
  651.   list = MSG_GetAttachmentList(mad->comppane);
  652. /*
  653.   list = MSG_GetCompHeader(mad->comppane, MSG_ATTACHMENTS_HEADER_MASK);
  654. */
  655.   while (list && list->url != NULL) {
  656.     fe_add_attachmentData(mad, list);
  657.     list++;
  658.   }
  659. }
  660.  
  661. Widget
  662. fe_make_managed_attach_form(MWContext* context, Widget parent)
  663. {
  664.   fe_ContextData* data = CONTEXT_DATA(context);
  665.   Widget list;
  666.   Widget messb;
  667.   Widget   attach_location, attach_file, delete_attach;
  668.   Widget kids [50];
  669.   Arg av [20];
  670.   int ac;
  671.   struct fe_mail_attach_data *mad = data->mad;
  672.   Widget label;
  673.   Widget   text_p, source_p, postscript_p;
  674.   Widget form;
  675.  
  676.  
  677.   XP_ASSERT(context->type == MWContextMessageComposition);
  678.  
  679.   if (mad)
  680.   {
  681.     fe_make_new_attach_list(context);
  682.     return NULL;
  683.   }
  684.  
  685.   ac = 0;
  686.   XtSetArg (av[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  687.   XtSetArg (av[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  688.   XtSetArg (av[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  689.   XtSetArg (av[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
  690.   form = XmCreateForm (parent, "attachForm", av, ac);
  691.  
  692.   ac = 0;
  693.   XtSetArg (av[ac], XmNdialogStyle, XmDIALOG_WORK_AREA); ac++;
  694.   XtSetArg (av[ac], XmNresizePolicy, XmRESIZE_GROW); ac++;
  695.   messb = XmCreateMessageBox(form, "messagebox", av, ac);
  696.   fe_UnmanageChild_safe(XmMessageBoxGetChild(messb, XmDIALOG_SEPARATOR));
  697.   fe_UnmanageChild_safe(XmMessageBoxGetChild(messb, XmDIALOG_OK_BUTTON));
  698.   fe_UnmanageChild_safe(XmMessageBoxGetChild(messb, XmDIALOG_CANCEL_BUTTON));
  699.   fe_UnmanageChild_safe(XmMessageBoxGetChild(messb, XmDIALOG_HELP_BUTTON));
  700.   ac = 0;
  701.   list = XmCreateScrolledList(messb, "list", av, ac);
  702.   attach_location = XmCreatePushButtonGadget(messb, "attachLocation", av, ac);
  703.   attach_file = XmCreatePushButtonGadget(messb, "attachFile", av, ac);
  704.   ac = 0;
  705.   XtSetArg (av[ac], XmNsensitive, False); ac++;
  706.   delete_attach = XmCreatePushButtonGadget(messb, "delete", av, ac);
  707.  
  708.  
  709.   ac = 0;
  710.   label = XmCreateLabelGadget (form, "label", av, ac);
  711.   ac = 0;
  712.   XtSetArg (av[ac], XmNset, False); ac++;
  713.   source_p = XmCreateToggleButtonGadget (form, "sourceToggle", av, ac);
  714.   text_p = XmCreateToggleButtonGadget (form, "textToggle", av, ac);
  715.   postscript_p = XmCreateToggleButtonGadget (form, "postscriptToggle", av, ac);
  716.  
  717.   /* Making the attachments in such a way that the list would grow is
  718.      the height of the dialog is increased */
  719.   XtVaSetValues (messb,
  720.          XmNtopAttachment, XmATTACH_FORM,
  721.          XmNbottomAttachment, XmATTACH_FORM,
  722.          XmNleftAttachment, XmATTACH_FORM,
  723.          XmNrightAttachment, XmATTACH_FORM,
  724.          0);
  725.   XtVaSetValues (label,
  726.                  XmNtopAttachment, XmATTACH_NONE,
  727.                  XmNbottomAttachment, XmATTACH_FORM,
  728.                  XmNleftAttachment, XmATTACH_FORM,
  729.                  XmNrightAttachment, XmATTACH_NONE,
  730.                  0);
  731.   XtVaSetValues (source_p,
  732.                  XmNtopAttachment, XmATTACH_NONE,
  733.                  XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
  734.                  XmNbottomWidget, label,
  735.                  XmNleftAttachment, XmATTACH_WIDGET,
  736.                  XmNleftWidget, label,
  737.                  XmNrightAttachment, XmATTACH_NONE,
  738.                  0);
  739.   XtVaSetValues (text_p,
  740.                  XmNtopAttachment, XmATTACH_NONE,
  741.                  XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
  742.                  XmNbottomWidget, label,
  743.                  XmNleftAttachment, XmATTACH_WIDGET,
  744.                  XmNleftWidget, source_p,
  745.                  XmNrightAttachment, XmATTACH_NONE,
  746.                  0);
  747.   XtVaSetValues (postscript_p,
  748.                  XmNtopAttachment, XmATTACH_NONE,
  749.                  XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
  750.                  XmNbottomWidget, label,
  751.                  XmNleftAttachment, XmATTACH_WIDGET,
  752.                  XmNleftWidget, text_p,
  753.                  XmNrightAttachment, XmATTACH_NONE,
  754.                  0);
  755.  
  756.  
  757. #ifdef dora_DEBUG
  758.   fprintf(stderr, "Creating new fe_mail_attach_data...\n");
  759. #endif
  760.   data->mad = mad = (struct fe_mail_attach_data *)
  761.     calloc (sizeof (struct fe_mail_attach_data), 1);
  762.   mad->nattachments = 0;
  763.  
  764.   mad->context = context;
  765.   mad->shell = 0;
  766.   mad->list = list;
  767.  
  768.   XtManageChild(list);
  769.   ac = 0;
  770.   kids [ac++] = attach_location;
  771.   kids [ac++] = mad->attach_file = attach_file;
  772.   kids [ac++] = mad->delete_attach = delete_attach;
  773.   XtManageChildren (kids, ac);
  774.   ac = 0;
  775.   kids [ac++] = messb;
  776.   kids [ac++] = label;
  777.   kids [ac++] = mad->source_p = source_p;
  778.   kids [ac++] = mad->text_p = text_p;
  779.   kids [ac++] = mad->postscript_p = postscript_p;
  780.  
  781.   XtManageChildren (kids, ac);
  782.   XtManageChild (form);
  783.  
  784.  
  785. #if 0
  786.   XtAddCallback (ok_button, XmNactivateCallback, fe_attachOk_cb, mad);
  787.   XtAddCallback (cancel_button, XmNactivateCallback, fe_attachCancel_cb, mad);
  788. #endif
  789.   XtAddCallback (attach_location, XmNactivateCallback,
  790.                     fe_attach_location_cb, mad);
  791.   XtAddCallback (attach_file, XmNactivateCallback, fe_attach_file_cb, mad);
  792.   XtAddCallback (delete_attach, XmNactivateCallback, fe_attach_delete_cb, mad);
  793.   XtAddCallback (list, XmNbrowseSelectionCallback, fe_attach_select_cb, mad);
  794.  
  795.   XtAddCallback (text_p,   XmNvalueChangedCallback,
  796.                  fe_attach_doc_type_cb, mad);
  797.   XtAddCallback (source_p, XmNvalueChangedCallback,
  798.                  fe_attach_doc_type_cb, mad);
  799.   XtAddCallback (postscript_p, XmNvalueChangedCallback,
  800.                  fe_attach_doc_type_cb, mad);
  801.  
  802.   /* Remember the last attachment typed used. */
  803.   XtVaSetValues((fe_last_attach_type == NULL ? source_p :
  804.                  strcmp(fe_last_attach_type, TEXT_PLAIN) == 0 ? text_p :
  805.                  strcmp(fe_last_attach_type,
  806.                         APPLICATION_POSTSCRIPT) == 0 ? postscript_p :
  807.                  source_p),
  808.                 XmNset, True, 0);
  809.  
  810.   return form;
  811. }
  812.  
  813. extern 
  814. void
  815. fe_MailComposeWin_ActivateFolder(MWContext *, int pos);
  816.  
  817. /* Prompts for attachment info.
  818.  */
  819. void
  820. fe_mailto_attach_dialog(MWContext* context)
  821. {
  822. #if 0
  823.   struct fe_mail_attach_data *mad = CONTEXT_DATA(context)->mad;
  824.   const struct MSG_AttachmentData *list;
  825.   int i;
  826. #endif
  827.  
  828.   XP_ASSERT(context->type == MWContextMessageComposition);
  829.   fe_MailComposeWin_ActivateFolder(context,1);
  830.  
  831. #if 0
  832.  
  833.   if (!mad || !mad->shell) {
  834. /*
  835.     fe_make_attach_dialog(context);
  836. */
  837.     mad = CONTEXT_DATA(context)->mad;
  838.   }
  839.  
  840.   /* Free the existing list of attachments */
  841.   XmListDeleteAllItems(mad->list);
  842.   for(i=0; i<mad->nattachments; i++) {
  843.     XP_FREE((char *)mad->attachments[i].url);
  844.   }
  845.   mad->nattachments = 0;
  846.     
  847.   /* Refresh the list of attachments */
  848.   list = MSG_GetAttachmentList(mad->comppane);
  849.   while (list && list->url != NULL) {
  850.     fe_add_attachmentData(mad, list);
  851.     list++;
  852.   }
  853.  
  854.   XtManageChild(mad->shell);
  855.   XMapRaised(XtDisplay(mad->shell), XtWindow(mad->shell));
  856. #endif
  857.   return;
  858. }
  859.  
  860.  
  861.  
  862. void
  863. fe_attach_dropfunc(Widget dropw, void* closure, fe_dnd_Event type,
  864.            fe_dnd_Source* source, XEvent* event)
  865. {
  866.   MWContext *compose_context;
  867.   MWContext *src_context;
  868.   const struct MSG_AttachmentData *old_list, *a;
  869.   struct MSG_AttachmentData *new_list;
  870.   Boolean sensitive_p = False;
  871.   char **urls, **ss;
  872.   const char *s;
  873.   char *str = NULL;
  874.   int old_count = 0;
  875.   int new_count = 0;
  876.   int i;
  877.  
  878.   if (type != FE_DND_DROP)
  879.     return;
  880.  
  881.   compose_context = (MWContext *) closure;
  882.   if (!compose_context) return;
  883.   XP_ASSERT(compose_context->type == MWContextMessageComposition);
  884.   if (compose_context->type != MWContextMessageComposition)
  885.     return;
  886.  
  887.   XtVaGetValues(CONTEXT_DATA(compose_context)->mcAttachments,
  888.         XmNsensitive, &sensitive_p, 0);
  889.   if (!sensitive_p)
  890.     {
  891.       /* If the Attachments field is not sensitive, then that means that
  892.      an attachment (or delivery?) is in progress, and bad things would
  893.      happen were we to try and attach things right now.  So just beep.
  894.        */
  895.       XBell (XtDisplay (CONTEXT_WIDGET(compose_context)), 0);
  896.       return;
  897.     }
  898.  
  899.   src_context = fe_WidgetToMWContext((Widget) source->closure);
  900.   if (!src_context) return;
  901.   switch (src_context->type)
  902.     {
  903.     case MWContextMail:
  904.     case MWContextNews:
  905.       /* ###tw  Should get a list of all the selected URLs from the mail/news
  906.        window...*/
  907.       urls = 0;
  908.       break;
  909.     case MWContextBookmarks:
  910.       /* #### Get a list of all the selected URLs out of the bookmarks
  911.      window... */
  912.       urls = 0;
  913.       break;
  914.     default:
  915.       XP_ASSERT(0);
  916.       urls = 0;
  917.       break;
  918.     }
  919.   if (!urls)
  920.     {
  921.       XBell (XtDisplay (CONTEXT_WIDGET(compose_context)), 0);
  922.       return;
  923.     }
  924.  
  925.   new_count = 0;
  926.   for (ss = urls; *ss; ss++)
  927.     new_count++;
  928.   XP_ASSERT(new_count > 0);
  929.   if (new_count <= 0) return; /* #### leaks `urls'; but it already asserted. */
  930.  
  931.   old_list = MSG_GetAttachmentList(CONTEXT_DATA(compose_context)->comppane);
  932.   old_count = 0;
  933.   if (old_list)
  934.     for (a = old_list; a->url; a++)
  935.       old_count++;
  936.  
  937.   new_list = (struct MSG_AttachmentData *)
  938.     XP_ALLOC(sizeof(struct MSG_AttachmentData) * (old_count + new_count + 1));
  939.  
  940.   for (i = 0; i < old_count; i++)
  941.     {
  942.       XP_MEMSET(&new_list[i], 0, sizeof(new_list[i]));
  943.       if (old_list[i].url)
  944.     new_list[i].url = XP_STRDUP(old_list[i].url);
  945.       if (old_list[i].desired_type)
  946.     new_list[i].desired_type = XP_STRDUP(old_list[i].desired_type);
  947.       if (old_list[i].real_type)
  948.     new_list[i].real_type = XP_STRDUP(old_list[i].real_type);
  949.       if (old_list[i].real_encoding)
  950.     new_list[i].real_encoding = XP_STRDUP(old_list[i].real_encoding);
  951.       if (old_list[i].real_name)
  952.     new_list[i].real_name = XP_STRDUP(old_list[i].real_name);
  953.       if (old_list[i].description)
  954.     new_list[i].description = XP_STRDUP(old_list[i].description);
  955.       if (old_list[i].x_mac_type)
  956.     new_list[i].x_mac_type = XP_STRDUP(old_list[i].x_mac_type);
  957.       if (old_list[i].x_mac_creator)
  958.     new_list[i].x_mac_creator = XP_STRDUP(old_list[i].x_mac_creator);
  959.     }
  960.  
  961.   if (new_count > 0)
  962.     XP_MEMSET(new_list + old_count, 0,
  963.           sizeof(struct MSG_AttachmentData) * (new_count + 1));
  964.  
  965.   i = old_count;
  966.   for (ss = urls; *ss; ss++)
  967.     new_list[i++].url = *ss;
  968.  
  969.   MSG_SetAttachmentList(CONTEXT_DATA(compose_context)->comppane, new_list);
  970.  
  971.   for (i = 0; i < old_count; i++)
  972.     {
  973.       if (new_list[i].url) XP_FREE((char*)new_list[i].url);
  974.       if (new_list[i].desired_type) XP_FREE((char*)new_list[i].desired_type);
  975.       if (new_list[i].real_type) XP_FREE((char*)new_list[i].real_type);
  976.       if (new_list[i].real_encoding) XP_FREE((char*)new_list[i].real_encoding);
  977.       if (new_list[i].real_name) XP_FREE((char*)new_list[i].real_name);
  978.       if (new_list[i].description) XP_FREE((char*)new_list[i].description);
  979.       if (new_list[i].x_mac_type) XP_FREE((char*)new_list[i].x_mac_type);
  980.       if (new_list[i].x_mac_creator) XP_FREE((char*)new_list[i].x_mac_creator);
  981.     }
  982.   XP_FREE (new_list);
  983.   for (ss = urls; *ss; ss++)
  984.     XP_FREE(*ss);
  985.   XP_FREE(urls);
  986.  
  987.   /* Now they're attached; update the display. */
  988.   s = MSG_GetCompHeader(CONTEXT_DATA(compose_context)->comppane,
  989.                         MSG_ATTACHMENTS_HEADER_MASK);
  990.  
  991.   if (s)
  992.   {
  993.     str = malloc(sizeof(char)*(strlen(s)+1));
  994.     strcpy(str, s);
  995.   }
  996.  
  997.   if (str) free(str);
  998. }
  999.