/* addresses.c */ #include "ml.h" Menu address_file_menu[] = { { NULL, "add", NUL_TERM, address_add, NULL, 0, NULL, NULL, BTN_SELECTION }, { NULL, "remove", NUL_TERM, address_remove, NULL, 0, NULL, NULL, BTN_NOSELECTION }, { NULL, "modify", NUL_TERM, address_modify, NULL, 0, NULL, NULL, BTN_NOSELECTION }, { NULL, "close_window", NUL_TERM, address_close_window, NULL, 0, NULL, NULL, BTN_ON }, }; Menu address_book_menu[] = { { NULL, "file_menu", NUL_TERM, NULL, address_file_menu, XtNumber(address_file_menu), NULL, NULL, BTN_ON }, { NULL, "search", NUL_TERM, address_search, NULL, 0, NULL, NULL, BTN_ON }, { NULL, "reset", NUL_TERM, address_reset, NULL, 0, NULL, NULL, BTN_ON }, { NULL, "HELP", NUL_TERM, address_help, NULL, 0, NULL, NULL, BTN_ON }, }; #ifdef __STDC__ Address_Book_Info *new_address_book_info(void) #else Address_Book_Info *new_address_book_info() #endif { Address_Book_Info *address_book_info = (Address_Book_Info *) fs_get(sizeof(Address_Book_Info)); address_book_info->name = NULL; address_book_info->address = NULL; address_book_info->comment = NULL; address_book_info->groups = NULL; address_book_info->next = NULL; address_book_info->prev = NULL; return(address_book_info); } #ifdef __STDC__ void free_address_book_info(Address_Book_Info *address_book_info) #else void free_address_book_info(address_book_info) Address_Book_Info *address_book_info; #endif { if(address_book_info != NULL) { if(address_book_info->name != NULL) fs_give((void **) &address_book_info->name); if(address_book_info->address != NULL) fs_give((void **) &address_book_info->address); if(address_book_info->comment != NULL) fs_give((void **) &address_book_info->comment); if(address_book_info->groups != NULL) fs_give((void **) &address_book_info->groups); fs_give((void **) &address_book_info); } return; } #ifdef __STDC__ void create_address_book_window(Tool w) #else void create_address_book_window(w) Tool w; #endif { Arg args[ARGLISTSIZE]; int n = 0; XtTranslations translations; Address_Book *address_book; Tool form, menubar; if(session->address_book != NULL) { if(session->address_book->is_realized == TRUE) de_iconify(session->address_book->shell); else { XtPopup(session->address_book->shell, XtGrabNone); session->address_book->is_realized = TRUE; } return; } address_book = (Address_Book *) fs_get(sizeof(Address_Book)); address_book->is_realized = FALSE; session->address_book = address_book; address_book->current = NULL; address_book->button_state = BTN_ON | BTN_NOSELECTION; XtSetArg (args[n], XmNdeleteResponse, XmDO_NOTHING); n++; address_book->shell = XtCreatePopupShell("address",topLevelShellWidgetClass, session->shell, args, n); AddDestroyCallback (address_book->shell); n = 0; setup_editres(address_book->shell); if(addr_icon != (Pixmap) None) XtVaSetValues(address_book->shell, XmNiconPixmap,addr_icon, NULL); form = XmCreateForm(address_book->shell, "form", args, n ); n = 0; XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n ++; XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++; XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++; menubar = XmCreateMenuBar(form, "menubar", args, n); n = 0; XtManageChild(menubar); create_buttons(NULL, menubar, address_book_menu, XtNumber(address_book_menu), address_book->button_state, (XtPointer) address_book, ROOTMENULEVEL); address_book->name = create_text_field(form, menubar, "name", NULL, 0, NULL, NULL); address_book->address = create_text_field(form, address_book->name, "addr", NULL, 0, NULL, NULL); address_book->groups = create_text_field(form, address_book->address, "grps", NULL, 0, NULL, NULL); address_book->comment = create_text_field(form, address_book->groups, "cmmt", NULL, 0, NULL, NULL); XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); n ++; XtSetArg(args[n], XmNlistSizePolicy, XmCONSTANT); n ++; XtSetArg(args[n], XmNselectionPolicy, XmSINGLE_SELECT); n ++; address_book->list = XmCreateScrolledList(form,"list",args,n); n = 0; XtAddCallback(address_book->list, XmNsingleSelectionCallback, (XtCallbackProc) address_book_select, address_book); XtAddCallback(address_book->list, XmNdefaultActionCallback, (XtCallbackProc) address_book_select, address_book); translations = XtParseTranslationTable(GLOBAL_addresses_pop_translations); XtOverrideTranslations(address_book->list, translations); XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++; XtSetArg(args[n], XmNtopWidget, address_book->comment); n ++; XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++; XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n ++; XtSetArg(args[n], XmNrightPosition, 50); n ++; XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n ++; XtSetValues(XtParent(address_book->list), args, n); n = 0; XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); n ++; XtSetArg(args[n], XmNlistSizePolicy, XmCONSTANT); n ++; XtSetArg(args[n], XmNselectionPolicy, XmSINGLE_SELECT); n ++; address_book->search_list = XmCreateScrolledList(form,"slist",args,n); n = 0; XtAddCallback(address_book->search_list, XmNsingleSelectionCallback, (XtCallbackProc) address_book_select, address_book); XtAddCallback(address_book->search_list, XmNdefaultActionCallback, (XtCallbackProc) address_book_select, address_book); translations = XtParseTranslationTable(GLOBAL_addresses_pop_translations); XtOverrideTranslations(address_book->search_list, translations); XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++; XtSetArg(args[n], XmNtopWidget, address_book->comment); n ++; XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++; XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n ++; XtSetArg(args[n], XmNleftPosition, 50); n ++; XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n ++; XtSetValues(XtParent(address_book->search_list), args, n); n = 0; XtAddCallback(address_book->shell, XmNpopdownCallback, (XtCallbackProc) address_book_popdown, address_book); XtAddCallback(address_book->shell, XmNdestroyCallback, (XtCallbackProc) address_book_destroy, address_book); address_sort(address_book); stuff_address_book(address_book); XtManageChild(address_book->search_list); XtManageChild(address_book->list); XtManageChild(form); XtManageChild(address_book->shell); XtPopup(address_book->shell,XtGrabNone); address_book->is_realized = TRUE; return; } #ifdef __STDC__ void address_close_window(Tool w,Address_Book *address_book,XtPointer xp) #else void address_close_window(w,address_book,xp) Tool w; Address_Book *address_book; XtPointer xp; #endif { XtPopdown(address_book->shell); address_book->is_realized = FALSE; return; } #ifdef __STDC__ void address_book_popdown(Tool w,Address_Book *address_book,XtPointer xp) #else void address_book_popdown(w,address_book,xp) Tool w; Address_Book *address_book; XtPointer xp; #endif { address_book->is_realized = FALSE; return; } #ifdef __STDC__ void address_book_destroy(Tool w,Address_Book *address_book,XtPointer xp) #else void address_book_destroy(w,address_book,xp) Tool w; Address_Book *address_book; XtPointer xp; #endif { XtDestroyWidget(address_book->shell); fs_give((void **) &session->address_book); session->address_book = NULL; return; } #ifdef __STDC__ void address_book_select(Tool w, Address_Book *address_book, XmListCallbackStruct *cb) #else void address_book_select(w,address_book,cb) Tool w; Address_Book *address_book; XmListCallbackStruct *cb; #endif { unsigned char *str; Address_Book_Info *info; Tool other; if(w == address_book->list) other = address_book->search_list; else other = address_book->list; XmListDeselectAllItems(other); XmStringGetLtoR(cb->item,XmSTRING_DEFAULT_CHARSET,(char **)&str); if((address_book->current != NULL) && (ml_strcoll(str,address_book->current->name) == STRMATCH) && (address_book->current_list == w)) { address_book_context_switch(address_book,address_book->current,NULL); address_book->button_state |= BTN_NOSELECTION; address_book->button_state &= ~BTN_SELECTION; } else { for(info = session->addresses; info ; info = info->prev ) { if((ml_strcoll(info->name,str)) == STRMATCH) { address_book_context_switch(address_book,address_book->current, info); address_book->button_state |= BTN_SELECTION; address_book->button_state &= ~BTN_NOSELECTION; } } } fs_give((void **) &str); address_book->current_list = w; check_buttons(address_book_menu, XtNumber(address_book_menu), NULL, address_book->button_state); return; } #ifdef __STDC__ void address_book_context_switch(Address_Book *address_book, Address_Book_Info *old, Address_Book_Info *new) #else void address_book_context_switch(address_book,old,new) Address_Book *address_book; Address_Book_Info *old; Address_Book_Info *new; #endif { if(old != NULL) { if(old->name != NULL) fs_give((void **) &old->name); old->name = GetUnTextField(address_book->name); if(old->address != NULL) fs_give((void **) &old->address); old->address = GetUnTextField(address_book->address); if(old->groups != NULL) fs_give((void **) &old->groups); old->groups = GetUnTextField(address_book->groups); if(old->comment != NULL) fs_give((void **) &old->comment); old->comment = GetUnTextField(address_book->comment); } if(new != NULL) { TextSetString(address_book->name, (new->name != NULL) ? new->name : (unsigned char *) EMPTYSTR); TextSetString(address_book->address, (new->address != NULL) ? new->address : (unsigned char *) EMPTYSTR); TextSetString(address_book->groups, (new->groups != NULL) ? new->groups : (unsigned char *) EMPTYSTR); TextSetString(address_book->comment, (new->comment != NULL) ? new->comment : (unsigned char *) EMPTYSTR); } else { TextSetString(address_book->name, (unsigned char *) EMPTYSTR); TextSetString(address_book->address,(unsigned char *) EMPTYSTR); TextSetString(address_book->groups, (unsigned char *) EMPTYSTR); TextSetString(address_book->comment,(unsigned char *) EMPTYSTR); } address_book->current = new; return; } #ifdef __STDC__ void stuff_address_book(Address_Book *address_book) #else void stuff_address_book(address_book) Address_Book *address_book; #endif { Address_Book_Info *info; XmString xstr; for(info = session->addresses; info ; info = info->prev) { xstr = XmStringCreateSimple((char *) info->name); XmListAddItemUnselected(address_book->list,xstr,0); XmStringFree(xstr); } return; } #ifdef __STDC__ void address_search(Tool w, Address_Book *address_book, XtPointer xp) #else void address_search(w,address_book,xp) Tool w; Address_Book *address_book; XtPointer xp; #endif { Address_Book_Info *info; XmString xstr; Boolean found = FALSE; /* Search on the current window contents */ unsigned char *name = GetUnTextField(address_book->name); unsigned char *address = GetUnTextField(address_book->address); unsigned char *groups = GetUnTextField(address_book->groups); unsigned char *comment = GetUnTextField(address_book->comment); /* Nothing to search for. */ if((*name == NUL_TERM) && (*address == NUL_TERM) && (*groups == NUL_TERM) && (*comment == NUL_TERM)) return; /* Let 'em know we're busy. */ push_cursor(WATCH_CURSOR); address_book->current = NULL; XmListDeleteAllItems(address_book->search_list); /* * Find a match on any field in our internal list, and * put it in the search list widget */ for(info = session->addresses; info; info = info->prev) { if((address_searchit(info->name,name)) || (address_searchit(info->address,address)) || (address_searchit(info->groups,groups)) || (address_searchit(info->comment,comment))) { found = TRUE; xstr = XmStringCreateSimple((char *) info->name); XmListAddItemUnselected(address_book->search_list,xstr,0); XmStringFree(xstr); } } /* * Popup the first one in the list. This will call our selection * callback before it's done, so we don't have to tweak anything. */ if(found) { XmListSelectPos(address_book->search_list,1,TRUE); } pop_cursor(); return; } /* * This isn't the best search algorithm, but it doesn't have to be. * We're looking for any substring match, case insensitive. * Empty strings or null strings don't count. */ /* i18n-broken */ #ifdef __STDC__ Boolean address_searchit(unsigned char *str,unsigned char *pat) #else Boolean address_searchit(str,pat) unsigned char *str; unsigned char *pat; #endif { register unsigned char *ptr; if((str == NULL) || (pat == NULL) || (*pat == NUL_TERM)) return(FALSE); for(ptr = str; *ptr; ptr ++ ) if(strncasecmp((char *) ptr,(char *) pat,strlen((char *)pat)) == STRMATCH) return(TRUE); return(FALSE); } #ifdef __STDC__ void address_remove(Tool w, Address_Book *address_book, XtPointer xp) #else void address_remove(w,address_book,xp) Tool w; Address_Book *address_book; XtPointer xp; #endif { Address_Book_Info *info = address_book->current; if(! info) return; if(preferences.confirmDestroy == TRUE) if((ml_confirm(address_book->shell, MLGetLocalized(XtNmsgDestroyAddress, MsgDestroyAddress), CONFIRM_OK_CANCEL)) == FALSE) return; if(info->prev) info->prev->next = info->next; if(info->next) info->next->prev = info->prev; else session->addresses = info->prev; if(address_book->current == info) address_book->current = NULL; free_address_book_info(info); push_cursor(WATCH_CURSOR); save_defaults(); address_reset(w,address_book, NULL); pop_cursor(); return; } #ifdef __STDC__ void address_add(Tool w, Address_Book *address_book, XtPointer xp) #else void address_add(w,address_book,xp) Tool w; Address_Book *address_book; XtPointer xp; #endif { Address_Book_Info *info; Address_Book_Info *curr; info = new_address_book_info(); info->name = GetUnTextField(address_book->name); if((info->name == NULL) || (*info->name == NUL_TERM)) { free_address_book_info(info); return; } for(curr = session->addresses; curr; curr = curr->prev) { if(ml_strcoll(curr->name,info->name) == STRMATCH) { free_address_book_info(info); return; } } push_cursor(WATCH_CURSOR); info->address = GetUnTextField(address_book->address); info->groups = GetUnTextField(address_book->groups); info->comment = GetUnTextField(address_book->comment); info->next = NULL; info->prev = session->addresses; if(info->prev) info->prev->next = info; session->addresses = info; address_sort(address_book); save_defaults(); address_reset(w,address_book, NULL); pop_cursor(); return; } #ifdef __STDC__ void address_modify(Tool w, Address_Book *address_book, XtPointer xp) #else void address_modify(w,address_book,xp) Tool w; Address_Book *address_book; XtPointer xp; #endif { Address_Book_Info *info; unsigned char *name = GetUnTextField(address_book->name); info = address_book->current; if((! info) || (*name == NUL_TERM)) return; push_cursor(WATCH_CURSOR); if(info->name) fs_give((void **) &info->name); info->name = name; if(info->address) fs_give((void **) &info->address); info->address = GetUnTextField(address_book->address); if(info->groups) fs_give((void **) &info->groups); info->groups = GetUnTextField(address_book->groups); if(info->comment) fs_give((void **) &info->comment); info->comment = GetUnTextField(address_book->comment); address_sort(address_book); save_defaults(); address_reset(w,address_book, NULL); pop_cursor(); return; } #ifdef __STDC__ void address_reset(Tool w, Address_Book *address_book, XtPointer xp) #else void address_reset(w,address_book,xp) Tool w; Address_Book *address_book; XtPointer xp; #endif { if(address_book == NULL) return; XmListDeleteAllItems(address_book->search_list); XmListDeselectAllItems(address_book->search_list); XmListDeselectAllItems(address_book->list); XmListDeleteAllItems(address_book->list); address_book->button_state |= BTN_NOSELECTION; address_book->button_state &= ~BTN_SELECTION; address_book_context_switch(address_book,address_book->current, NULL); stuff_address_book(address_book); check_buttons(address_book_menu, XtNumber(address_book_menu), NULL, address_book->button_state); return; } #ifdef __STDC__ int address_compare(const void *adr1, const void *adr2) #else int address_compare(adr1,adr2) const void *adr1; const void *adr2; #endif { Address_Book_Info **a1 = (Address_Book_Info **) adr1; Address_Book_Info **a2 = (Address_Book_Info **) adr2; return(ml_strcoll((*(a1))->name,(*(a2))->name)); } #ifdef __STDC__ void address_sort(Address_Book *address_book) #else void address_sort(address_book) Address_Book *address_book; #endif { Address_Book_Info **sort; Address_Book_Info *info; int n = 0; int total = 0; if(session->addresses == NULL) return; for(info = session->addresses; info; info = info->prev) total ++; if(total < 2) return; sort = (Address_Book_Info **) fs_get(total * sizeof(Address_Book_Info *)); for(info = session->addresses; info; info = info->prev) { sort[n] = info; n ++; } qsort((char *) sort,total,sizeof(Address_Book_Info **),address_compare); for(n = 0; n < total; n ++) { info = sort[n]; if(n == 0) { session->addresses = info; info->next = NULL; info->prev = sort[n + 1]; } else { info->next = sort[n - 1]; if(n == (total - 1)) info->prev = NULL; else info->prev = sort[n + 1]; } } fs_give((void **) &sort); return; } #ifdef __STDC__ void address_help(Tool w, Address_Book *address_book, XtPointer xp) #else void address_help(w,address_book,xp) Tool w; Address_Book *address_book; XtPointer xp; #endif { help(address_book->shell, ADDRESSBOOKHELPFILE); return; } #ifdef __STDC__ ADDRESS *text_to_address(char *text,char *host) #else ADDRESS *text_to_address(text,host) char *text; char *host; #endif { ADDRESS *address = NULL; if(host == NULL) host = EMPTYSTR; if((text != NULL) && (*text != NUL_TERM)) rfc822_parse_adrlist(&address,text,host); return(address); } #ifdef __STDC__ ADDRESS *copy_address(ADDRESS *src_address) #else ADDRESS *copy_address(src_address) ADDRESS *src_address; #endif { ADDRESS *new_address = (ADDRESS*) NULL; new_address = mail_newaddr(); if ((new_address != NULL) && (src_address != NULL)) { new_address->personal = ((src_address->personal) ? cpystr(src_address->personal) : NULL); new_address->adl = ((src_address->adl) ? cpystr(src_address->adl) : NULL); new_address->mailbox = ((src_address->mailbox) ? cpystr(src_address->mailbox) : NULL); new_address->host = ((src_address->host) ? cpystr(src_address->host) : NULL ); new_address->error = ((src_address->error) ? cpystr(src_address->error) : NULL); if (src_address->next) new_address->next = copy_address( src_address->next ); } return(new_address); } #ifdef __STDC__ void local_make_addr_str(ADDRESS *adr, char *obuf) #else void local_make_addr_str(adr, obuf) ADDRESS *adr; char *obuf; #endif { if ((!adr) || (adr->mailbox == NULL)) { sprintf(obuf, SPACESTR); return; } if ((adr->personal != NULL) && (adr->host != NULL)) sprintf(obuf, "\"%s\" <%s@%s>", adr->personal, adr->mailbox, adr->host); else { if(adr->host != NULL) sprintf(obuf, "%s@%s", adr->mailbox, adr->host); else sprintf(obuf,"%s",adr->mailbox); } return; } #ifdef __STDC__ int save_address_book(FILE *fp) #else int save_address_book(fp) FILE *fp; #endif { Address_Book_Info *info; if(session->addresses == NULL) return(0); fprintf(fp,"\n%s\n",BEGIN_ADDRESS_STR); for(info = session->addresses; info ; info = info->prev) { fprintf(fp,"*%s\n",(info->name != NULL) ? (char *) info->name : EMPTYSTR); fprintf(fp,"%s\n",(info->address != NULL) ? (char *) info->address : EMPTYSTR); fprintf(fp,"%s\n",(info->groups != NULL) ? (char *) info->groups : EMPTYSTR); fprintf(fp,"%s\n",(info->comment != NULL) ? (char *) info->comment : EMPTYSTR); } fprintf(fp,"%s\n",END_ADDRESS_STR); return(0); } #ifdef __STDC__ int load_address_book(FILE *fp) #else int load_address_book(fp) FILE *fp; #endif { char buffer[FILEBUFFLEN]; Boolean new_style = FALSE; Address_Book_Info *info; char *ptr; while((fgets(buffer,sizeof(buffer),fp)) != NULL) { buffer[strlen(buffer)-1] = '\0'; if((strcmp(buffer,END_ADDRESS_STR)) == STRMATCH) return(0); info = new_address_book_info(); ptr = buffer; if(*ptr == '*') { ptr ++; new_style = TRUE; } info->name = (unsigned char *) cpystr(ptr); if(fgets(buffer,sizeof(buffer),fp)) { buffer[strlen(buffer)-1] = '\0'; info->address = (unsigned char *) cpystr(buffer); } else info->address = (unsigned char *) cpystr(EMPTYSTR); if(new_style == TRUE) { if(fgets(buffer,sizeof(buffer),fp)) { buffer[strlen(buffer)-1] = '\0'; info->groups = (unsigned char *) cpystr(buffer); } else info->groups = (unsigned char *) cpystr(EMPTYSTR); } if(fgets(buffer,sizeof(buffer),fp)) { buffer[strlen(buffer)-1] = '\0'; info->comment = (unsigned char *) cpystr(buffer); } else info->comment = (unsigned char *) cpystr(EMPTYSTR); if(session->addresses == NULL) session->addresses = info; else { info->prev = session->addresses; session->addresses->next = info; session->addresses = info; } } return(0); } #ifdef __STDC__ void addresses_pop(Widget w, XtPointer xp) #else void addresses_pop(w,xp) Widget w; XtPointer xp; #endif { address_close_window(w,session->address_book,NULL); return; }