/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* SearchRuleView.cpp -- creates each rule statement. Created: Dora Hsu , 15-Dec-96 */ #include "MNSearchView.h" #include "SearchRuleView.h" #include "EditHdrDialog.h" #include #include #include #include #include #include #include #include #include // For search date #include /* for XP_GetString() */ #include #include #include "xp_time.h" #include "xplocale.h" /* External routines which now live in Menu.cpp */ extern "C" { Boolean fe_set_current_attribute_option(Widget parent, int btnPos ); Widget fe_make_option_menu(Widget toplevel, Widget parent, char* widgetName, Widget *popup); void fe_get_option_size (Widget optionMenu, Dimension *retWidth, Dimension *retHeight); }; extern int XFE_SEARCH_INVALID_DATE; extern int XFE_SEARCH_INVALID_MONTH; extern int XFE_SEARCH_INVALID_DAY; extern int XFE_SEARCH_INVALID_YEAR; //--- notification --- const char *XFE_SearchRuleView::activateSearch = "XFE_SearchRuleView::activateSearch"; //--- C utilities function --- /*--------------------------------------------------------------- This part should be belonging to libmsg. This part is copied from winfe ----------------------------------------------------------------*/ extern "C" MSG_SearchError MSG_GetValuesForAttribute( MSG_ScopeAttribute /*scope*/, MSG_SearchAttribute attrib, MSG_SearchMenuItem *items, uint16 *maxItems) { int32 status; const int32 aiStatiValues[] = { MSG_FLAG_READ, MSG_FLAG_REPLIED, MSG_FLAG_FORWARDED}; const MSG_PRIORITY aiPriorityValues[] = { MSG_LowestPriority, MSG_LowPriority, MSG_NormalPriority, MSG_HighPriority, MSG_HighestPriority }; uint16 nStati = sizeof(aiStatiValues) / sizeof(int32); uint16 nPriorities = sizeof(aiPriorityValues) / sizeof(MSG_PRIORITY); uint16 i; switch (attrib) { case attribPriority: for ( i = 0; i < nPriorities && i < *maxItems; i++ ) { items[i].attrib = (int16) aiPriorityValues[i]; MSG_GetPriorityName( (MSG_PRIORITY) items[i].attrib, items[i].name, sizeof( items[i].name) / sizeof(char) ); items[i].isEnabled = TRUE; } *maxItems = i; if ( i == nPriorities ) { return SearchError_Success; } else { return SearchError_ListTooSmall; } case attribMsgStatus: for ( i = 0; i < nStati && i< *maxItems; i++ ) { items[i].attrib = (int16) aiStatiValues[i]; status = (int32) items[i].attrib; MSG_GetStatusName( status, items[i].name, sizeof( items[i].name) / sizeof(char) ); items[i].isEnabled = TRUE; } *maxItems = i; if ( i == nStati ) { return SearchError_Success; } else { return SearchError_ListTooSmall; } default: *maxItems = 0; return SearchError_InvalidAttribute; } } // --------- Constructor XFE_SearchRuleView::XFE_SearchRuleView(XFE_Component *toplevel_component, Widget parent, XFE_View *parent_view, MWContext *context, MSG_Pane *p, char *title, void *folderInfo, MSG_ScopeAttribute curScope, uint16 curAttrib) : XFE_MNView(toplevel_component, parent_view, context, p) { XP_ASSERT(p!= NULL); { initializeDataMember(); m_curScope = curScope; m_curAttribIndex = curAttrib; m_ruleTitle = (char*)XP_STRDUP(title); } { /* Get Visual, Colormap, and Depth */ XtVaGetValues(getToplevel()->getBaseWidget(), XmNvisual, &m_visual, XmNcolormap, &m_cmap, XmNdepth, &m_depth, NULL); } m_opt_valueField = NULL; m_date_valueField = NULL; m_date_textField = NULL; m_text_valueField = NULL; if ( curScope == scopeLdapDirectory ) m_dir = (DIR_Server*)folderInfo; else m_folderInfo = (MSG_FolderInfo*)folderInfo; createWidgets(parent); getToplevel()->registerInterest( XFE_MNSearchView::scopeChanged, this, (XFE_FunctionNotification)scopeChanged_cb); getToplevel()->registerInterest(XFE_Component::afterRealizeCallback, this, (XFE_FunctionNotification)afterRealizeWidget_cb); } XFE_SearchRuleView::~XFE_SearchRuleView() { getToplevel()->unregisterInterest( XFE_MNSearchView::scopeChanged, this, (XFE_FunctionNotification)scopeChanged_cb); getToplevel()->unregisterInterest(XFE_Component::afterRealizeCallback, this, (XFE_FunctionNotification)afterRealizeWidget_cb); } void XFE_SearchRuleView:: initializeDataMember() { // Init data here m_height = 0; } void XFE_SearchRuleView::createWidgets(Widget parent) { MSG_SearchMenuItem *attrItems; MSG_SearchMenuItem *opItems; MSG_SearchValueWidget valueType; MSG_SearchError err; uint16 attrNum; uint16 opNum; DIR_Server *dirs[1]; MSG_FolderInfo *folderInfos[1]; opItems = (MSG_SearchMenuItem*) XP_CALLOC(kNumOperators, sizeof(MSG_SearchMenuItem)); opNum = kNumOperators; if ( m_curScope != scopeLdapDirectory ) { folderInfos[0]= (MSG_FolderInfo *)m_folderInfo; MSG_GetNumAttributesForSearchScopes(fe_getMNMaster(), m_curScope, (void**)folderInfos, 1, &attrNum); attrItems = (MSG_SearchMenuItem *)XP_CALLOC(attrNum, sizeof(MSG_SearchMenuItem)); err = MSG_GetAttributesForSearchScopes(fe_getMNMaster(), m_curScope, (void**)folderInfos, 1, attrItems, &attrNum); } else { if ( m_dir ) { dirs[0]= (DIR_Server*) m_dir; MSG_GetNumAttributesForSearchScopes(fe_getMNMaster(), m_curScope, (void**)dirs, 1, &attrNum); attrItems = (MSG_SearchMenuItem *)XP_CALLOC(attrNum, sizeof(MSG_SearchMenuItem)); err = MSG_GetAttributesForSearchScopes(fe_getMNMaster(), m_curScope, (void**)dirs, 1, attrItems, &attrNum); } else return; } if ( err != SearchError_Success ) return; // water fall display, display the next attribute // Caller needs to garuntee that m_curAttrib is less than attrNum if ((uint16)m_curAttribIndex >= attrNum ) m_curAttribIndex =0 ; if (m_curScope != scopeLdapDirectory ) { err = MSG_GetOperatorsForSearchScopes(fe_getMNMaster(), m_curScope, (void**)folderInfos, 1, (MSG_SearchAttribute)(attrItems[m_curAttribIndex].attrib), opItems, &opNum); } else { err = MSG_GetOperatorsForSearchScopes(fe_getMNMaster(), m_curScope, (void**)dirs, 1, (MSG_SearchAttribute)(attrItems[m_curAttribIndex].attrib), opItems, &opNum); } if ( err == SearchError_Success ) { err = MSG_GetSearchWidgetForAttribute( (MSG_SearchAttribute)(attrItems[m_curAttribIndex].attrib), &valueType); if ( err == SearchError_Success ) { buildRules(parent, m_curScope, m_curAttribIndex, attrItems, attrNum, opItems, opNum, valueType ); fe_set_current_attribute_option( m_attr_opt, m_curAttribIndex); fe_set_current_attribute_option( m_op_opt, 0); } } /* FREE CALLOC data */ XP_FREE(attrItems); XP_FREE(opItems); } void XFE_SearchRuleView::setLabelWidth(Dimension width) { // This method should be called after view // is created so that the layout would be fine if (m_label) XtVaSetValues(m_label, XmNwidth, width, XmNalignment, XmALIGNMENT_END, XmNrecomputeSize, False, 0 ); if ( m_attr_opt ) XtVaSetValues( m_attr_opt, XmNleftOffset, width, 0); } void XFE_SearchRuleView::buildRules(Widget parent, MSG_ScopeAttribute curScope, uint16 newAttr, MSG_SearchMenuItem attrItems[], uint16 attrNum, MSG_SearchMenuItem opItems[], uint16 opNum, MSG_SearchValueWidget valueType ) { Arg av[20]; Widget formW; m_curScope = curScope; m_attr = (MSG_SearchAttribute)(attrItems[newAttr].attrib); m_op = (MSG_SearchOperator)(opItems[0].attrib); m_type = valueType; if ( !getBaseWidget() ) { formW = XmCreateForm(parent, "searchRulesForm", av, 0); setBaseWidget(formW); } else formW = getBaseWidget(); m_label = XtVaCreateManagedWidget( m_ruleTitle, xmLabelGadgetClass, formW, NULL ); /* Attrib */ m_attr_opt = fe_make_option_menu(getToplevel()->getBaseWidget(), formW, "searchAttrOpt", &m_attr_pop); buildPulldownMenu(m_attr_pop, attrItems, attrNum, attribOptionCallback, (XtPointer)this); /* Operator */ m_op_opt = fe_make_option_menu(getToplevel()->getBaseWidget(), formW, "searchOpOpt", &m_op_pop); buildPulldownMenu(m_op_pop, opItems, opNum, operatorOptionCallback, (XtPointer)this); /* Calculate form size */ calculateSize(); /* Values */ m_value = replaceValueField(NULL, formW, valueType, NULL, NULL); //XtManageChild(m_value); m_type = valueType; /* Doing layout */ if ( m_label ) XtVaSetValues( m_label, XmNheight, m_height, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, 0); if ( m_attr_opt ) XtVaSetValues( m_attr_opt, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, 0); if ( m_op_opt ) XtVaSetValues( m_op_opt, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, (m_attr_opt? XmATTACH_OPPOSITE_WIDGET: XmATTACH_NONE), XmNbottomWidget, m_attr_opt, XmNleftAttachment, (m_attr_opt? XmATTACH_WIDGET: XmATTACH_NONE), XmNleftWidget, m_attr_opt, XmNrightAttachment, XmATTACH_NONE, 0); if ( m_value ) { XtVaSetValues( m_value, XmNtopAttachment, (m_op_opt? XmATTACH_OPPOSITE_WIDGET: XmATTACH_NONE), XmNtopWidget, m_op_opt, XmNbottomAttachment, (m_op_opt? XmATTACH_OPPOSITE_WIDGET: XmATTACH_NONE), XmNbottomWidget, m_op_opt, XmNleftAttachment, (m_op_opt? XmATTACH_WIDGET: XmATTACH_NONE), XmNleftWidget, m_op_opt, XmNrightAttachment, XmATTACH_FORM, 0); } XtVaSetValues(formW, XmNheight, m_height, XmNtopAttachment, XmATTACH_NONE, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, 0); XtManageChild(m_attr_opt); XtManageChild(m_op_opt); XtManageChild(formW); } void XFE_SearchRuleView::changeLabel(char* newlabel) { XmString xmlabl = XmStringCreateSimple(newlabel); XtVaSetValues(m_label, XmNlabelString, xmlabl, 0); XmStringFree(xmlabl); } void XFE_SearchRuleView::buildPulldownMenu(Widget pulldownParent, MSG_SearchMenuItem items[], uint16 itemNum, XtCallbackProc activeCB, XtPointer clientData) { int i; XmString xmStr; Arg av[20]; int ac; Widget btn; WidgetList childrenList; int numChildren; int attribData; int iitemNum = (int)itemNum; /* Clean up first */ XtVaGetValues( pulldownParent, XmNchildren, &childrenList, XmNnumChildren, &numChildren, 0); for ( i = 0; i < numChildren; i++ ) { XtDestroyWidget(childrenList[i]); } /* Create new ones... */ Boolean otherHdrs = FALSE; for ( i = 0; i < iitemNum; i++ ) { attribData = (int)(items[i].attrib); if (!otherHdrs && attribData == attribOtherHeader) { XtVaCreateManagedWidget("sep", xmSeparatorGadgetClass, pulldownParent, 0); otherHdrs = TRUE; } xmStr = XmStringCreateSimple(items[i].name); ac = 0; XtSetArg(av[ac], XmNuserData, attribData); ac++; XtSetArg(av[ac], XmNlabelString, xmStr); ac++; btn = XmCreatePushButtonGadget(pulldownParent, "ruleBtn", av, ac); XtAddCallback(btn, XmNactivateCallback, activeCB, clientData); XtManageChild(btn); XmStringFree(xmStr); } if (pulldownParent == m_attr_pop) { // Add the "Edit Custom Hdr" button: XtVaCreateManagedWidget("sep", xmSeparatorGadgetClass, pulldownParent, 0); btn = XtVaCreateManagedWidget("editHdrBtn", xmPushButtonGadgetClass, pulldownParent, 0); XtAddCallback(btn, XmNactivateCallback, editHdrCallback, this); } } void XFE_SearchRuleView::attribOptionCallback(Widget w, XtPointer clientData, XtPointer /*callData*/) { XFE_SearchRuleView *obj = (XFE_SearchRuleView*)clientData; XtPointer attribData; int16 n; XtVaGetValues(w, XmNuserData, &attribData, 0); int iattribData = (int)attribData; n = (int16)iattribData; obj->setAttribOption(n); } void XFE_SearchRuleView::createValueWidgetSet(Widget /*parent*/) { } void XFE_SearchRuleView::setAttribOption(int16 attrib) { MSG_SearchError err; MSG_SearchValueWidget valueType; MSG_SearchMenuItem *opItems; uint16 opNum = kNumOperators; /* XP relies on this value to know array size */ XtUnmanageChild(getBaseWidget()); opItems = (MSG_SearchMenuItem*) XP_CALLOC(kNumOperators, sizeof(MSG_SearchMenuItem)); if ( m_attr != attrib) { XtUnmanageChild(m_attr_opt); XtUnmanageChild(m_op_opt); m_attr = (MSG_SearchAttribute)attrib; m_curAttribIndex = (uint16) m_attr; if (m_curScope != scopeLdapDirectory ) { MSG_FolderInfo *folderInfos[1]; folderInfos[0]= (MSG_FolderInfo *)m_folderInfo; err = MSG_GetOperatorsForSearchScopes(fe_getMNMaster(), m_curScope, (void**)folderInfos, 1, (MSG_SearchAttribute)m_attr, opItems, &opNum); } else { DIR_Server *dirs[1]; dirs[0]= (DIR_Server*) m_dir; err = MSG_GetOperatorsForSearchScopes(fe_getMNMaster(), m_curScope, (void**)dirs, 1, (MSG_SearchAttribute)m_attr, opItems, &opNum); } if (err == SearchError_Success ) { err = MSG_GetSearchWidgetForAttribute(m_attr, &valueType); if ( err == SearchError_Success ) { if ( needNewMenu(m_op_pop, opItems, opNum )) { XtUnmanageChild(m_op_opt); XtDestroyWidget(m_op_opt); m_op_opt = fe_make_option_menu(getToplevel()->getBaseWidget(), getBaseWidget(), "searchOpOpt", &m_op_pop); buildPulldownMenu(m_op_pop, opItems, opNum, operatorOptionCallback, (XtPointer)this); fe_set_current_attribute_option( m_op_opt, 0); /* Operator may have been changed */ m_op = (MSG_SearchOperator)(opItems[0].attrib); /* Use the new one */ XtVaSetValues( m_op_opt, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, (m_attr_opt? XmATTACH_OPPOSITE_WIDGET: XmATTACH_NONE), XmNbottomWidget, m_attr_opt, XmNleftAttachment, (m_attr_opt? XmATTACH_WIDGET: XmATTACH_NONE), XmNleftWidget, m_attr_opt, XmNrightAttachment, XmATTACH_NONE, 0); } XtManageChild(m_attr_opt); XtManageChild(m_op_opt); /* Build new value */ m_value = replaceValueField(m_value, getBaseWidget(), //XtParent(m_value), valueType, NULL, (XtPointer)NULL); } /* success */ } /* success*/ } XtManageChild(getBaseWidget()); if (valueType == widgetText) XmProcessTraversal(m_text_valueField, XmTRAVERSE_CURRENT); else if (valueType == widgetDate) XmProcessTraversal(m_date_textField, XmTRAVERSE_CURRENT); /* FREE CALLOC data */ XP_FREE(opItems); } Boolean XFE_SearchRuleView::needNewMenu(Widget pulldownParent, MSG_SearchMenuItem *opItems, uint16 opNum ) { int numChildren; WidgetList childrenList; XtPointer data; int idata; uint16 data16; int i, j; Boolean found; int iopNum = (int)opNum; XtVaGetValues( pulldownParent, XmNchildren, &childrenList, XmNnumChildren, &numChildren, 0); // if ( numChildren != opNum ) return True; for ( i = 0; i < numChildren; i++ ) { XtVaGetValues( childrenList[i], XmNuserData, &data, 0 ); idata = (int)data; data16= (uint16)idata; found = True; for ( j = 0; j < iopNum; j++ ) { if ( data16 != opItems[j].attrib ) { found = False; break; } } if ( !found ) return True; } return False; } void XFE_SearchRuleView::operatorOptionCallback(Widget w, XtPointer clientData, XtPointer /*callData*/) { XFE_SearchRuleView *obj = (XFE_SearchRuleView*)clientData; XtPointer opData; int iopData; int16 n; XtVaGetValues(w, XmNuserData, &opData, 0); iopData = (int)opData; n = (int16)iopData; obj->m_op= (MSG_SearchOperator)n; } void XFE_SearchRuleView::valueOptionCallback(Widget w, XtPointer clientData, XtPointer /*callData*/) { XFE_SearchRuleView *obj = (XFE_SearchRuleView*)clientData; XtPointer valueData; int ivalueData; uint16 n; XtVaGetValues(w, XmNuserData, &valueData, 0); ivalueData = (int)valueData; n = (int16)ivalueData; obj->m_value_option = n; } void XFE_SearchRuleView::calculateSize() { Dimension width, height; WidgetList childrenList; int numChildren; XtVaGetValues( m_attr_pop, XmNchildren, &childrenList, XmNnumChildren, &numChildren, 0 ); if ( numChildren > 0 ) { fe_get_option_size(m_attr_opt, &width, &height ); if (width > m_width) m_width = width; if (height > m_height) m_height = height; } XtVaGetValues( m_op_pop, XmNchildren, &childrenList, XmNnumChildren, &numChildren, 0 ); if ( numChildren > 0 ) { fe_get_option_size(m_op_opt, &width, &height ); if (width > m_width) m_width = width+20; if (height > m_height) m_height = height+20; } } Widget XFE_SearchRuleView::replaceValueField ( Widget valueField, Widget parent, MSG_SearchValueWidget valueType, XtCallbackProc callback, XtPointer clientData) { Arg av[20]; int ac; Widget newField = NULL; MSG_SearchMenuItem *items; uint16 maxItems = 16; Widget lblField; Visual* v = 0; Colormap cmap = 0; Cardinal depth = 0; if (!valueField) { // Create everything for the first time... // Create Menu Widget Widget popup; m_opt_valueField = fe_make_option_menu(getToplevel()->getBaseWidget(), parent, "op_valueField", &popup); // Create Date Widget ac = 0; m_date_valueField = XmCreateForm(parent, "date_valueField", av, ac ); m_date_textField= fe_CreateTextField(m_date_valueField, "textValueField", av, ac ); XtAddCallback(m_date_textField, XmNactivateCallback, typeActivateCallback, this); lblField = XmCreateLabelGadget(m_date_valueField, "labelValueField", av, ac); XtVaSetValues(m_date_textField, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, XfeWidth(lblField) + 6, 0 ); XtVaSetValues(lblField, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, 0 ); XtManageChild(m_date_textField); XtManageChild(lblField); // Widget Text ac = 0; m_text_valueField= fe_CreateTextField(parent, "text_valueField", av, ac ); XtAddCallback(m_text_valueField, XmNactivateCallback, typeActivateCallback, this); // set up attachment #if 0 XtVaSetValues( m_opt_valueField, XmNleftWidget, m_op_opt, XmNleftAttachment, XmATTACH_WIDGET, XmNrightAttachment, XmATTACH_FORM, XmNbottomWidget, m_op_opt, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, m_op_opt, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, 0); XtVaSetValues( m_date_valueField, XmNleftWidget, m_op_opt, XmNleftAttachment, XmATTACH_WIDGET, XmNrightAttachment, XmATTACH_FORM, XmNbottomWidget, m_op_opt, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, m_op_opt, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, 0); XtVaSetValues( m_text_valueField, XmNleftWidget, m_op_opt, XmNleftAttachment, XmATTACH_WIDGET, XmNrightAttachment, XmATTACH_FORM, XmNbottomWidget, m_op_opt, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, m_op_opt, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, 0); #endif } else { #if 0 ac = 0; XtSetArg(av[ac], XmNleftAttachment, XmATTACH_NONE); ac++; XtSetArg(av[ac], XmNbottomAttachment, XmATTACH_NONE); ac++; XtSetArg(av[ac], XmNrightAttachment, XmATTACH_NONE); ac++; XtSetArg(av[ac], XmNtopAttachment, XmATTACH_NONE); ac++; XtSetValues(valueField, av, ac); #endif XtUnmanageChild(valueField); } m_type = valueType; switch(valueType ) { case widgetMenu: { if ( m_opt_valueField) { // Get the popup widget, and destroy them for creating new ones #if 0 ac = 0; XtSetArg(av[ac], XmNleftAttachment, XmATTACH_NONE); ac++; XtSetArg(av[ac], XmNbottomAttachment, XmATTACH_NONE); ac++; XtSetArg(av[ac], XmNrightAttachment, XmATTACH_NONE); ac++; XtSetArg(av[ac], XmNtopAttachment, XmATTACH_NONE); ac++; XtSetValues(m_opt_valueField, av,ac); #endif Widget popup; XtUnmanageChild(m_opt_valueField); XtDestroyWidget(m_opt_valueField); m_opt_valueField = fe_make_option_menu(getToplevel()->getBaseWidget(), parent, "op_valueField", &popup); popup = NULL; XtVaGetValues(m_opt_valueField, XmNsubMenuId, &popup, 0 ); if ( popup ) XtDestroyWidget(popup); XtVaSetValues(m_opt_valueField, XmNsubMenuId, NULL, 0 ); XtVaGetValues(getToplevel()->getBaseWidget(), XtNvisual, &v, XtNcolormap, &cmap, XtNdepth, &depth, 0); ac = 0; XtSetArg(av[ac], XmNvisual, v); ac++; XtSetArg(av[ac], XmNdepth, depth); ac++; XtSetArg(av[ac], XmNcolormap, cmap); ac++; popup= XmCreatePulldownMenu(parent, "Pulldown", av, ac); items = (MSG_SearchMenuItem*) XP_CALLOC(maxItems, sizeof(MSG_SearchMenuItem)); MSG_GetValuesForAttribute(m_curScope, m_attr, items, &maxItems ); buildPulldownMenu(popup, items, maxItems, valueOptionCallback, (XtPointer)this); XtVaSetValues(m_opt_valueField, XmNsubMenuId, popup, 0); /* FREE CALLOC data */ XP_FREE(items); } } newField = m_opt_valueField; break; case widgetDate: { /* Create default date time */ char dateStr[40], tmp[16]; time_t now = XP_TIME(); XP_StrfTime(m_contextData, dateStr, sizeof(dateStr), XP_DATE_TIME_FORMAT, localtime(&now)); XP_STRNCPY_SAFE(tmp, dateStr, 9); fe_SetTextField(m_date_textField, tmp); if ( callback ) XtAddCallback(m_date_textField, XmNvalueChangedCallback, callback, clientData); } newField = m_date_valueField; break; case widgetText: if ( callback ) XtAddCallback(m_text_valueField, XmNvalueChangedCallback, callback, clientData); newField = m_text_valueField; break; case widgetInt: if ( callback ) XtAddCallback(m_text_valueField, XmNvalueChangedCallback, callback, clientData); newField = m_text_valueField; break; default: XP_ASSERT (0); return 0; } ac = 0; XtSetArg(av[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++; XtSetArg(av[ac], XmNbottomWidget, m_op_opt); ac++; XtSetArg(av[ac], XmNrightAttachment, XmATTACH_FORM); ac++; XtSetArg(av[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++; XtSetArg(av[ac], XmNtopWidget, m_op_opt); ac++; XtSetValues(newField,av,ac); XtSetMappedWhenManaged(newField, TRUE); ac = 0; XtSetArg(av[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++; XtSetArg(av[ac], XmNleftWidget, m_op_opt); ac++; XtSetArg(av[ac], XmNleftOffset, 0);ac++; XtSetValues(newField,av,ac); XtSetMappedWhenManaged(newField, TRUE); XtManageChild(newField); return newField; } XFE_CALLBACK_DEFN(XFE_SearchRuleView,afterRealizeWidget)(XFE_NotificationCenter *, void *, void*) { // put focus in text field: XmProcessTraversal(m_text_valueField, XmTRAVERSE_CURRENT); } void XFE_SearchRuleView::resetSearchValue() { if ( m_date_textField ) { /* Reset date */ char dateStr[40], tmp[16]; time_t now = XP_TIME(); XP_StrfTime(m_contextData, dateStr, sizeof(dateStr), XP_DATE_TIME_FORMAT, localtime(&now)); XP_STRNCPY_SAFE(tmp, dateStr, 9); fe_SetTextField(m_date_textField, tmp); } if ( m_text_valueField ) { /* Reset text value */ fe_SetTextFieldAndCallBack(m_text_valueField, ""); } #if 0 /* Reset all the search rules */ if ( m_type == widgetText ) { if (m_value && XmIsTextField(m_value)) fe_SetTextFieldAndCallBack(m_value, ""); } else if ( m_type == widgetDate) { Widget textW; textW = XtNameToWidget(m_value, "textValueField"); fe_SetTextFieldAndCallBack(textW, ""); } /* Don't change the option back at all ... Need to check with HI about this... else fe_search_set_current_attribute_option(curlist->value, 0); */ #endif } XP_Bool fe_getDate (char *string, int* mm, int* dd, int* yyyy) { char *cp; cp = strtok(string, "/"); if (cp && strspn(cp, "0123456789") == strlen(cp)) { *mm = atoi(cp); if (*mm > 12 || *mm < 1) *mm = -1; } else { *mm = -1; #ifdef DEBUG_dora printf("error in month\n"); #endif } cp = strtok(NULL, "/"); if (cp && strspn(cp, "0123456789") == strlen(cp)) { *dd = atoi(cp); if (*dd > 31 || *dd < 1) *dd = -1; } else { *dd = -1; #ifdef DEBUG_dora printf ("error in day\n"); #endif } cp = strtok(NULL, "\0"); if (cp && strspn(cp, "0123456789") == strlen(cp)) { *yyyy = atoi(cp); if (*yyyy < 1900) *yyyy = -1; } else { *yyyy = -1; #ifdef DEBUG_dora printf("error in year\n"); #endif } #ifdef DEBUG_dora printf("mon = %d, day = %d, year = %d\n", *mm, *dd, *yyyy); #endif if ( *mm == -1 || *dd == -1 || *yyyy == -1) return False; return True; } time_t fe_mkTime(int mon, int day, int year) { time_t t; struct tm time_str; time_str.tm_year = year - 1900; time_str.tm_mon = mon-1; time_str.tm_mday = day; time_str.tm_hour = 0; time_str.tm_min = 0; time_str.tm_sec = 1; time_str.tm_isdst = -1; // ignore daylight saving t = mktime(&time_str); #ifdef DEBUG_dora if (t == -1) printf("mktime error\n"); else printf("time = %d\n", t); #endif return t; } XP_Bool XFE_SearchRuleView::getSearchTerm( MSG_SearchAttribute *attr, MSG_SearchOperator *op, MSG_SearchValue *value, char* customHdr) { Widget textW; char *string = 0; char *label; XP_Bool no_err = True; if ( m_type == widgetText || m_type == widgetInt ) string = fe_GetTextField(m_value); else if ( m_type == widgetDate) { string = NULL; textW = XtNameToWidget(m_value, "textValueField"); string = fe_GetTextField(textW); } value->attribute = m_attr; switch (m_attr) { case attribDate: { value->u.date = XP_ParseTimeString(string, False); XtFree(string); } break; case attribPriority: value->u.priority = (MSG_PRIORITY)(m_value_option); break; case attribMsgStatus: value->u.msgStatus = m_value_option; break; case attribAgeInDays: value->u.age = XP_ATOI(string); break; case attribOtherHeader: value->u.string = string; label = getAttribLabel(); strcpy(customHdr, label); XtFree(label); break; default: value->u.string = XP_STRDUP(string); } if (string) XtFree(string); *attr = m_attr; *op = m_op; return no_err; } // Result of getAttribLabel should be XtFree()ed char* XFE_SearchRuleView::getAttribLabel() { Widget lablW; XtVaGetValues(m_attr_opt, XmNmenuHistory, &lablW, 0); XmString xmstr; XtVaGetValues(lablW, XmNlabelString, &xmstr, 0); char* lablstr; XmStringGetLtoR(xmstr, XmSTRING_DEFAULT_CHARSET, &lablstr); return lablstr; } void XFE_SearchRuleView::editHeaders() { #undef DEFEAT_RACE_CONDITION // BE API not ready yet #ifdef DEFEAT_RACE_CONDITION // Defeat race condition between this dialog and the search view MSG_Master* master = fe_getMNMaster(); if (!master->AcquireEditHeadersSemaphore(this)) { #ifdef DEBUG_akkana printf("SearchRuleView: Couldn't get semaphore! Punting ...\n"); #endif return; } #endif /* DEFEAT_RACE_CONDITION */ XFE_EditHdrDialog* d = new XFE_EditHdrDialog(getToplevel()->getBaseWidget(), "editHdrDialog", getContext()); char* newhdr = d->post(); #ifdef DEFEAT_RACE_CONDITION if (!master->ReleaseEditHeadersSemaphore(this)) { #ifdef DEBUG_akkana printf("SearchRuleView: Couldn't release semaphore!\n"); #endif return; } #endif /* DEFEAT_RACE_CONDITION */ // // Set our option menu to something reasonable, // since it can't stay on "Customize..." // Future work: notify our parent so it updates the menus of // all the other SearchRuleViews as well (like the Filter UI does). resetHeaderOptions(newhdr); if (newhdr) free(newhdr); } void XFE_SearchRuleView::resetHeaderOptions(char* newhdr) { if ( m_curScope == scopeLdapDirectory ) return; // Get the list of attributes again from the backend: MSG_FolderInfo *folderInfos[1]; folderInfos[0]= (MSG_FolderInfo *)m_folderInfo; uint16 attrNum = 0; MSG_GetNumAttributesForSearchScopes(fe_getMNMaster(), m_curScope, (void**)folderInfos, 1, &attrNum); MSG_SearchMenuItem* attrItems = (MSG_SearchMenuItem *)XP_CALLOC(attrNum, sizeof(MSG_SearchMenuItem)); int err = MSG_GetAttributesForSearchScopes(fe_getMNMaster(), m_curScope, (void**)folderInfos, 1, attrItems, &attrNum); if (err != SearchError_Success) return; buildPulldownMenu(m_attr_pop, attrItems, attrNum, attribOptionCallback, (XtPointer)this); // Get the new menu items: int numChildren; WidgetList childrenList; XtVaGetValues(m_attr_pop, XmNchildren, &childrenList, XmNnumChildren, &numChildren, 0); if (newhdr == 0) { XtVaSetValues(m_attr_opt, XmNmenuHistory, childrenList[0], 0); attribOptionCallback(childrenList[0], (XtPointer)this, NULL); return; } // Loop over the option menu's options and make sure they match // the current set of arbitrary headers: char* thisbtn = 0; for (int num = 0; num < numChildren; ++num) { XmString xmstr; XtVaGetValues(childrenList[num], XmNlabelString, &xmstr, 0); XmStringGetLtoR(xmstr, XmFONTLIST_DEFAULT_TAG, &thisbtn); if (thisbtn && !XP_STRCMP(thisbtn, newhdr)) { // Set the option menu to show that string XtVaSetValues(m_attr_opt, XmNmenuHistory, childrenList[num], 0); attribOptionCallback(childrenList[num], (XtPointer)this, NULL); break; } } if (thisbtn) XtFree(thisbtn); } void XFE_SearchRuleView::changeScope(MSG_FolderInfo *folderInfo) { /* Find out what scope this folder is ++ */ if ( m_curScope != scopeLdapDirectory) { m_folderInfo = folderInfo; MSG_FolderLine folderLine; MSG_GetFolderLineById(XFE_MNView::getMaster(), folderInfo, &folderLine); if (folderLine.flags & (MSG_FOLDER_FLAG_NEWSGROUP | MSG_FOLDER_FLAG_NEWS_HOST)) { /* News */ m_curScope = scopeNewsgroup; } else m_curScope = scopeMailFolder; } /* Find out what scope this folder is -- */ /* destroyRules */ Widget form = getBaseWidget(); Widget parent = XtParent(form); int i, numChildren; WidgetList childrenList; Dimension leadingWidth; XtVaGetValues(form, XmNnumChildren, &numChildren, XmNchildren, &childrenList, 0); leadingWidth = getLeadingWidth(); for ( i = 0; i < numChildren; i++ ) { XtDestroyWidget(childrenList[i]); } createWidgets(parent); adjustLeadingWidth(leadingWidth); } XFE_CALLBACK_DEFN(XFE_SearchRuleView, scopeChanged)(XFE_NotificationCenter*, void *, void *calldata) { if ( m_curScope == scopeLdapDirectory ) { m_dir = (DIR_Server *)calldata; changeScope(NULL); } else { MSG_FolderInfo* folder = (MSG_FolderInfo*)calldata; changeScope(folder); } } uint16 XFE_SearchRuleView::getAttributeIndex() { return m_curAttribIndex; } Dimension XFE_SearchRuleView::getLeadingWidth() { Dimension width; XtVaGetValues(m_label, XmNwidth, &width, NULL); return width; } void XFE_SearchRuleView::adjustLeadingWidth(Dimension width) { XtVaSetValues(m_attr_opt, XmNleftOffset, width, 0); XtVaSetValues(m_label, XmNwidth, width, XmNrecomputeSize, False, 0 ); } Dimension XFE_SearchRuleView::getHeight() { return m_height; } void XFE_SearchRuleView::typeActivateCallback(Widget /* w */, XtPointer clientData, XtPointer /* callData */) { XFE_SearchRuleView *obj = (XFE_SearchRuleView*) clientData; obj->getToplevel()->notifyInterested( XFE_SearchRuleView::activateSearch, (void*) NULL); } void XFE_SearchRuleView::editHdrCallback(Widget, XtPointer clientData, XtPointer /*calldata*/ ) { XFE_SearchRuleView* srv = (XFE_SearchRuleView *) clientData; srv->editHeaders(); }