home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / EditHdrDialog.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  11.5 KB  |  384 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.   EditHdrDialog.cpp -- add or remove arbitrary mail headers.
  20.   Created: Akkana Peck <akkana@netscape.com>, 19-Nov-97.
  21.  */
  22.  
  23.  
  24.  
  25. #include "EditHdrDialog.h"
  26.  
  27. #include "xp_str.h"
  28. #include "prefapi.h"
  29. #include "xpgetstr.h"
  30.  
  31. #include <Xm/Form.h>
  32. #include <Xm/List.h>
  33. #include <Xm/RowColumn.h>
  34. #include <Xm/LabelG.h>
  35. #include <Xm/TextF.h>
  36. #include <Xm/ToggleBG.h>
  37. #include <Xm/PushBG.h>
  38.  
  39. // we need this in the post() method.
  40. extern "C" void fe_EventLoop();
  41.  
  42. extern "C" char *
  43. XFE_PromptWithCaption(MWContext *context, const char *caption,
  44.               const char *message, const char *deflt);
  45.  
  46. extern int XFE_CUSTOM_HEADER;   // for XP_GetString
  47.  
  48. XFE_EditHdrDialog::XFE_EditHdrDialog(Widget parent, char *name,
  49.                                      MWContext* context)
  50.     : XFE_Dialog(parent, 
  51.                  name, 
  52.                  TRUE, // ok
  53.                  TRUE, // cancel
  54.                  FALSE, // help
  55.                  FALSE, // apply
  56.                  TRUE, // separator
  57.                  TRUE // modal
  58.         )
  59. {
  60.     m_contextData = context;
  61.  
  62.     Widget form = XtCreateManagedWidget("dialogForm",
  63.                                         xmFormWidgetClass,
  64.                                         m_chrome,
  65.                                         NULL, 0);
  66.     Widget labl = XtVaCreateManagedWidget("editHdrLabel",
  67.                                           xmLabelGadgetClass, form,
  68.                                           XmNtopAttachment, XmATTACH_FORM,
  69.                                           XmNleftAttachment, XmATTACH_FORM,
  70.                                           XmNrightAttachment, XmATTACH_FORM,
  71.                                           0);
  72.     Widget rc = XtVaCreateManagedWidget("buttonRC",
  73.                                         xmRowColumnWidgetClass, form,
  74.                                         XmNorientation, XmVERTICAL,
  75.                                         XmNtopAttachment, XmATTACH_WIDGET,
  76.                                         XmNtopWidget, labl,
  77.                                         XmNrightAttachment, XmATTACH_FORM,
  78.                                         XmNbottomAttachment, XmATTACH_FORM,
  79.                                         0);
  80.  
  81.     Arg av[8];
  82.     int ac = 0;
  83. //    XtSetArg(av[ac], XmNvisibleItemCount, 6); ac++;
  84.     XtSetArg(av[ac], XmNselectionPolicy, XmEXTENDED_SELECT); ac++;
  85.     XtSetArg(av[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  86.     XtSetArg(av[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
  87.     XtSetArg(av[ac], XmNrightWidget, rc); ac++;
  88.     XtSetArg(av[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  89.     XtSetArg(av[ac], XmNtopWidget, labl); ac++;
  90.     XtSetArg(av[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
  91.     m_list = XmCreateScrolledList(form, "hdrList", av, ac);
  92.     XtManageChild(m_list);
  93.     XtAddCallback(m_list, XmNdefaultActionCallback, butn_cb, this);
  94.     XtAddCallback(m_list, XmNextendedSelectionCallback, select_cb, this);
  95.  
  96.     Widget butn = XtCreateManagedWidget("new",
  97.                                         xmPushButtonGadgetClass, rc,
  98.                                         NULL, 0);
  99.     XtAddCallback(butn, XmNactivateCallback, butn_cb, this);
  100.     m_editButton = XtCreateManagedWidget("edit",
  101.                                          xmPushButtonGadgetClass, rc,
  102.                                          NULL, 0);
  103.     XtAddCallback(m_editButton, XmNactivateCallback, butn_cb, this);
  104.     m_deleteButton = XtCreateManagedWidget("delete",
  105.                                            xmPushButtonGadgetClass, rc,
  106.                                            NULL, 0);
  107.     XtAddCallback(m_deleteButton, XmNactivateCallback, butn_cb, this);
  108.  
  109.     // Edit and delete buttons aren't turned on until something is selected:
  110.     XtSetSensitive(m_editButton, FALSE);
  111.     XtSetSensitive(m_deleteButton, FALSE);
  112.  
  113.     XtAddCallback(m_chrome, XmNokCallback, ok_cb, this);
  114.     XtAddCallback(m_chrome, XmNcancelCallback, cancel_cb, this);
  115. }
  116.  
  117. XFE_EditHdrDialog::~XFE_EditHdrDialog()
  118. {
  119.     // nothing needed (that I'm aware of) yet.
  120. }
  121.  
  122. //
  123. // It's not completely clear whether the string returned here should be
  124. // freed or not.  Currently we're not freeing it.
  125. // The code eventually ends up in dialogs.c and it's not clear
  126. // where the string is coming from.
  127. // The only other place I can find where fe_prompt is used
  128. // is in MNView.cpp, which also does not free the result.
  129. //
  130. char *
  131. XFE_EditHdrDialog::promptHeader(char* oldhdr)
  132. {
  133.     char* newhdr = XFE_PromptWithCaption(m_contextData,
  134.                                          "",
  135.                                          XP_GetString(XFE_CUSTOM_HEADER),
  136.                                          oldhdr);
  137.     
  138.  
  139.     return newhdr;
  140. }
  141.  
  142. char*
  143. XFE_EditHdrDialog::post()
  144. {
  145.     m_doneWithLoop = False;
  146.   
  147.     XtVaSetValues(m_chrome,
  148.                   XmNdeleteResponse, XmUNMAP,
  149.                   NULL);
  150.  
  151.     // Get the current list of custom headers and show them in the list:
  152.     XmListDeleteAllItems(m_list);
  153.     int lengthOfHdrPref = 0;
  154.     PREF_GetCharPref("mailnews.customHeaders", 0, &lengthOfHdrPref);
  155.     if (lengthOfHdrPref > 0)
  156.     {
  157.         char* buf = new char [lengthOfHdrPref];
  158.         PREF_GetCharPref("mailnews.customHeaders", buf, &lengthOfHdrPref);
  159.         if (lengthOfHdrPref > 0)
  160.         {
  161.             char* sep = " ";
  162.             char* placeholder = 0;
  163.             char* next;
  164.             char* strtokbuf = buf;
  165.             while (next = XP_STRTOK_R(strtokbuf, sep, &placeholder))
  166.             {
  167.                 strtokbuf = 0;        // only want it for first XP_STRTOK_R call
  168.                 while (isspace(*next))
  169.                     ++next;
  170.                 XmString item = XmStringCreateSimple(next);
  171.                 XmListAddItem(m_list, item, 0);
  172.                 XmStringFree(item);
  173.             }
  174.         }
  175.     }
  176.  
  177.     show();
  178.     while(!m_doneWithLoop)
  179.         fe_EventLoop();
  180.  
  181.     if (!m_retVal)
  182.         return 0;
  183.  
  184.     // User hit OK, so return the currently selected header:
  185.     int* posList = 0;
  186.     int posCount = 0;
  187.     XmListGetSelectedPos(m_list, &posList, &posCount);
  188.     if (!posCount)
  189.         return 0;
  190.  
  191.     int itemCount;
  192.     XmString* items;
  193.     char* hdr;
  194.     XtVaGetValues(m_list,
  195.                   XmNitemCount, &itemCount,
  196.                   XmNitems, &items,
  197.                   0);
  198.  
  199.     if (posList[0]-1 >= itemCount)
  200.         return 0;
  201.  
  202.     XmStringGetLtoR(items[posList[0]-1], XmFONTLIST_DEFAULT_TAG, &hdr);
  203.  
  204.     if (posList)
  205.         XtFree((char*)posList);
  206.  
  207.     return hdr;     // yes, this return value should be freed by the caller
  208. }
  209.  
  210. void
  211. XFE_EditHdrDialog::selection(XmListCallbackStruct* cbs)
  212. {
  213.     if (cbs->selected_item_count > 0)
  214.         XtSetSensitive(m_deleteButton, TRUE);
  215.     else
  216.         XtSetSensitive(m_deleteButton, FALSE);
  217.     if (cbs->selected_item_count == 1)
  218.         XtSetSensitive(m_editButton, TRUE);
  219.     else
  220.         XtSetSensitive(m_editButton, FALSE);
  221. }
  222.  
  223. //
  224. // Handle new/edit/delete buttons and default action callback.
  225. // w is the widget (button or list) which caused the callback.
  226. //
  227. void
  228. XFE_EditHdrDialog::button(Widget w)
  229. {
  230.     if (*(XtName(w)) == 'n')         // New button
  231.     {
  232.         // bring up an empty new-header dialog
  233.         char* newhdr = promptHeader(0);
  234.         if (newhdr)
  235.         {
  236.             XmListDeselectAllItems(m_list);
  237.             XmString xmhdr = XmStringCreateSimple(newhdr);
  238.             XmListAddItem(m_list, xmhdr, 0);
  239.             XmListSelectPos(m_list, 0, FALSE);
  240.             XmStringFree(xmhdr);
  241.  
  242.             // This should leave the new header selected, so turn on buttons:
  243.             XtSetSensitive(m_editButton, TRUE);
  244.             XtSetSensitive(m_deleteButton, TRUE);
  245.         }
  246.  
  247.         return;
  248.     }
  249.  
  250.     int* posList = 0;
  251.     int posCount = 0;
  252.     XmListGetSelectedPos(m_list, &posList, &posCount);
  253.     if (posCount <= 0 || posList == 0)
  254.     {
  255.         if (posList)
  256.             XtFree((char*)posList);
  257.         return;
  258.     }
  259.  
  260.     if (w == m_deleteButton)
  261.     {
  262.         XmListDeletePositions(m_list, posList, posCount);
  263.  
  264.         // Now nothing is selected, so turn off edit/delete buttons:
  265.         XtSetSensitive(m_editButton, FALSE);
  266.         XtSetSensitive(m_deleteButton, FALSE);
  267.     }
  268.     else if (w == m_list || w == m_editButton)
  269.     {
  270.         int whichitem = posList[0] - 1;
  271.         int itemCount;
  272.         XmString* items;
  273.         char* hdr;
  274.         XtVaGetValues(m_list,
  275.                       XmNitemCount, &itemCount,
  276.                       XmNitems, &items,
  277.                       0);
  278.         XmStringGetLtoR(items[whichitem], XmFONTLIST_DEFAULT_TAG, &hdr);
  279.         if (hdr)
  280.         {
  281.             char* newhdr = promptHeader(hdr);
  282.             if (newhdr)
  283.             {
  284.                 XmString xmhdr = XmStringCreateSimple(newhdr);
  285.                 XmListReplaceItemsPos(m_list, &xmhdr, 1, posList[0]);
  286.                 XmStringFree(xmhdr);
  287.             }
  288.             XtFree(hdr);
  289.         }
  290.     }
  291.  
  292.     XtFree((char*)posList);
  293. }
  294.  
  295. void
  296. XFE_EditHdrDialog::ok()
  297. {
  298.     m_doneWithLoop = True;
  299.     m_retVal = True;
  300.  
  301.     // Save the current set of headers in the pref "mailnews.customHeaders":
  302.     XmString* items;
  303.     int itemCount;
  304.     XtVaGetValues(m_list,
  305.                   XmNitemCount, &itemCount,
  306.                   XmNitems, &items,
  307.                   0);
  308.  
  309.     // first, figure out how many chars we need to allocate:
  310.     int totalLength = 0;
  311.     int i;
  312.     for (i=0; i < itemCount; ++i)
  313.     {
  314.         char* next;
  315.         XmStringGetLtoR(items[i], XmFONTLIST_DEFAULT_TAG, &next);
  316.         if (next)
  317.         {
  318.             totalLength += XP_STRLEN(next) + 1;
  319.             XtFree(next);
  320.         }
  321.     }
  322.  
  323.     char* buf = new char [totalLength];
  324.     buf[0] = '\0';
  325.     for (i=0; i < itemCount; ++i)
  326.     {
  327.         char* next;
  328.         XmStringGetLtoR(items[i], XmFONTLIST_DEFAULT_TAG, &next);
  329.         if (next)
  330.         {
  331.             if (i > 0)
  332.                 XP_STRCAT(buf, " ");
  333.             XP_STRCAT(buf, next);
  334.             XtFree(next);
  335.         }
  336.     }
  337.  
  338.     PREF_SetCharPref("mailnews.customHeaders", buf);
  339.             
  340.     hide();
  341. }
  342.  
  343. void
  344. XFE_EditHdrDialog::cancel()
  345. {
  346.     m_doneWithLoop = True;
  347.     m_retVal = False;
  348.  
  349.     hide();
  350. }
  351.  
  352. void 
  353. XFE_EditHdrDialog::ok_cb(Widget, XtPointer clientData, XtPointer)
  354. {
  355.     XFE_EditHdrDialog *obj = (XFE_EditHdrDialog*)clientData;
  356.  
  357.     obj->ok();
  358. }
  359.  
  360. void
  361. XFE_EditHdrDialog::cancel_cb(Widget, XtPointer clientData, XtPointer)
  362. {
  363.     XFE_EditHdrDialog *obj = (XFE_EditHdrDialog*)clientData;
  364.  
  365.     obj->cancel();
  366. }
  367.  
  368. void
  369. XFE_EditHdrDialog::butn_cb(Widget w, XtPointer clientData, XtPointer)
  370. {
  371.     XFE_EditHdrDialog *obj = (XFE_EditHdrDialog*)clientData;
  372.  
  373.     obj->button(w);
  374. }
  375.  
  376. void
  377. XFE_EditHdrDialog::select_cb(Widget, XtPointer clientData, XtPointer callData)
  378. {
  379.     XFE_EditHdrDialog *obj = (XFE_EditHdrDialog*)clientData;
  380.  
  381.     obj->selection((XmListCallbackStruct *)callData);
  382. }
  383.  
  384.