diff options
author | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
---|---|---|
committer | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
commit | 094ca96844842928810f14844413109fc6cdd890 (patch) | |
tree | e60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /pith/adrbklib.h | |
download | alpine-094ca96844842928810f14844413109fc6cdd890.tar.xz |
Initial Alpine Version
Diffstat (limited to 'pith/adrbklib.h')
-rw-r--r-- | pith/adrbklib.h | 857 |
1 files changed, 857 insertions, 0 deletions
diff --git a/pith/adrbklib.h b/pith/adrbklib.h new file mode 100644 index 00000000..6b148251 --- /dev/null +++ b/pith/adrbklib.h @@ -0,0 +1,857 @@ +/* + * $Id: adrbklib.h 1012 2008-03-26 00:44:22Z hubert@u.washington.edu $ + * + * ======================================================================== + * Copyright 2006-2008 University of Washington + * Copyright 2013 Eduardo Chappa + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * ======================================================================== + */ + +#ifndef PITH_ADRBKLIB_INCLUDED +#define PITH_ADRBKLIB_INCLUDED + + +#include "../pith/indxtype.h" +#include "../pith/remtype.h" +#include "../pith/store.h" +#include "../pith/string.h" + + +/* + * Some notes: + * + * The order that the address book is stored in on disk is the order that + * the entries will be displayed in. When an address book is opened, + * if it is ReadWrite the sort order is checked and it is sorted if it is + * out of order. + * + * Considerable complexity that previously existed in the address book + * code has been removed. Cpu speeds have improved significantly and + * memory has increased dramatically, as well. The cost of the complexity + * of the lookup file and hashtables and all that stuff is thought to be + * more than the benefits. See pre-5.00 pine adrbklib.h for the way it + * used to be. + * + * The display code has remained the same. + * There is also some allocation happening + * in addrbook.c. In particular, the display is a window into an array + * of rows, at least one row per addrbook entry plus more for lists. + * Each row is an AddrScrn_Disp structure and those should typically take + * up 6 or 8 bytes. A cached copy of addrbook entries is not kept, just + * the element number to look it up (and often get it out of the EntryRef + * cache). In order to avoid having to allocate all those rows, this is + * also in the form of a cache. Only 3 * screen_length rows are kept in + * the cache, and the cache is always a simple interval of rows. That is, + * rows between valid_low and valid_high are all in the cache. Row numbers + * in the display list are a little mysterious. There is no origin. That + * is, you don't necessarily know where the start or end of the display + * is. You only know how to go forward and backward and how to "warp" + * to new locations in the display and go forward and backward from there. + * This is because we don't know how many rows there are all together. It + * is also a way to avoid searching through everything to get somewhere. + * If you want to go to the End, you warp there and start backwards instead + * of reading through all the entries to get there. If you edit an entry + * so that it sorts into a new location, you warp to that new location to + * save processing all of the entries in between. + * + * + * Notes about RFC1522 encoding: + * + * If the fullname field contains other than US-ASCII characters, it is + * encoded using the rules of RFC1522 or its successor. The value actually + * stored in the file is encoded, even if it matches the character set of + * the user. This is so it is easy to pass the entry around or to change + * character sets without invalidating entries in the address book. When + * a fullname is displayed, it is first decoded. If the fullname field is + * encoded as being from a character set other than the user's character + * set, that will be retained until the user edits the field. Then it will + * change over to the user's character set. The comment field works in + * the same way, as do the "phrase" fields of any addresses. On outgoing + * mail, the correct character set will be retained if you use ComposeTo + * from the address book screen. However, if you use a nickname from the + * composer or ^T from the composer, the character set will be lost if it + * is different from the user's character set. + * + * + * Notes about RemoteViaImap address books: + * + * There are currently two types of address books, Local and Imap. Local means + * it is in a local file. Imap means it is stored in a folder on a remote + * IMAP server. The folder is a regular folder containing mail messages but + * the messages are special. The first message is a header message. The last + * message is the address book data. In between messages are old versions of + * the address book data. The address book data is stored in the message as + * it would be on disk, with no fancy mime encoding or anything. When it is + * used the data from the last message in the folder is copied to a local file + * and then it is used just like a local file. The local file is a cache for + * the remote data. We can tell the remote data has been changed by looking + * at the Date of the last message in the remote folder. If we see it has + * changed we copy the whole file over again and replace the cache file. + * A possibly quicker way to tell if it has changed is if the UID has + * changed or the number of messages in the folder has changed. We use those + * methods if possible since they don't require opening a new stream and + * selecting the folder. There is one metadata file for address book data. + * The name of that file is stored in the pinerc file. It contains the names + * of the cache files for RemoveViaImap address books plus other caching + * information for those address books (uid...). + */ + +#define NFIELDS 11 /* one more than num of data fields in addrbook entry */ + +/* + * The type a_c_arg_t is a little confusing. It's the type we use in + * place of adrbk_cntr_t when we want to pass an adrbk_cntr_t in an argument. + * We were running into problems with the integral promotion of adrbk_cntr_t + * args. A_c_arg_t has to be large enough to hold a promoted adrbk_cntr_t. + * So, if adrbk_cntr_t is unsigned short, then a_c_arg_t needs to be int if + * int is larger than short, or unsigned int if short is same size as int. + * Since usign16_t always fits in a short, a_c_arg_t of unsigned int should + * always work for !HUGE. For HUGE, UINT32 will be either an unsigned int + * or an unsigned long. If it is an unsigned long, then a_c_arg_t better be + * an unsigned long, too. If it is an unsigned int, then a_c_arg_t could + * be an unsigned int, too. However, if we just make it unsigned long, then + * it will be the same in all cases and big enough in all cases. + */ + +#define adrbk_cntr_t UINT32 /* addrbook counter type */ +typedef unsigned long a_c_arg_t; /* type of arg passed for adrbk_cntr_t */ +#define NO_NEXT ((adrbk_cntr_t)-1) +#define MAX_ADRBK_SIZE (2000000000L) /* leave room for extra display lines */ + +/* + * The value NO_NEXT is reserved to mean that there is no next address, or that + * there is no address number to return. This is similar to getc returning + * -1 when there is no char to get, but since we've defined this to be + * unsigned we need to reserve one of the valid values for this purpose. + * With current implementation it needs to be all 1's, so memset initialization + * will work correctly. + */ + +typedef enum {NotSet, Single, List} Tag; + + +/* This is what is actually used by the routines that manipulate things */ +typedef struct adrbk_entry { + char *nickname; /* UTF-8 */ + char *fullname; /* of simple addr or list (stored in UTF-8) */ + union addr { + char *addr; /* for simple Single entries */ + char **list; /* for distribution lists */ + } addr; + char *fcc; /* fcc specific for when sending to this address */ + char *extra; /* comments field (stored in UTF-8) */ + char referenced; /* for detecting loops during lookup */ + Tag tag; /* single addr (Single) or a list (List) */ +} AdrBk_Entry; + + +typedef struct abook_tree_node { + struct abook_tree_node *down; /* next letter of nickname */ + struct abook_tree_node *right; /* alternate letter of nickname */ + char value; /* character at this node */ + adrbk_cntr_t entrynum; /* use NO_NEXT as no-data indicator */ +} AdrBk_Trie; + + +/* information useful for displaying the addrbook */ +typedef struct width_stuff { + int max_nickname_width; + int max_fullname_width; + int max_addrfield_width; + int max_fccfield_width; + int third_biggest_fullname_width; + int third_biggest_addrfield_width; + int third_biggest_fccfield_width; +} WIDTH_INFO_S; + + +typedef struct expanded_list { + adrbk_cntr_t ent; + struct expanded_list *next; +} EXPANDED_S; + + +typedef enum {Local, Imap} AdrbkType; + + +#ifndef IMAP_IDLE_TIMEOUT +#define IMAP_IDLE_TIMEOUT (10L * 60L) /* seconds */ +#endif +#ifndef FILE_VALID_CHK_INTERVAL +#define FILE_VALID_CHK_INTERVAL ( 15L) /* seconds */ +#endif +#ifndef LOW_FREQ_CHK_INTERVAL +#define LOW_FREQ_CHK_INTERVAL (240) /* minutes */ +#endif + +typedef struct adrbk { + AdrbkType type; /* type of address book */ + char *orig_filename; /* passed in filename */ + char *filename; /* addrbook filename */ + char *our_filecopy; /* session copy of filename contents */ + FILE *fp; /* fp for our_filecopy */ + adrbk_cntr_t count; /* how many entries in addrbook */ + adrbk_cntr_t del_count; /* how many #DELETED entries in abook */ + AdrBk_Entry *arr; /* array of entries */ + AdrBk_Entry *del; /* array of deleted entries */ + AdrBk_Trie *nick_trie; + AdrBk_Trie *addr_trie; + AdrBk_Trie *full_trie; + AdrBk_Trie *revfull_trie; + time_t last_change_we_know_about;/* to look for others changing it*/ + time_t last_local_valid_chk;/* when valid check was done */ + unsigned flags; /* see defines in alpine.h (DEL_FILE...)*/ + WIDTH_INFO_S widths; /* helps addrbook.c format columns */ + int sort_rule; + EXPANDED_S *exp; /* this is for addrbook.c to use. A + list of expanded list entry nums is kept here */ + EXPANDED_S *checks; /* this is for addrbook.c to use. A + list of checked entry nums is kept here */ + EXPANDED_S *selects; /* this is for addrbook.c to use. A + list of selected entry nums is kept here */ + REMDATA_S *rd; +} AdrBk; + + +/* + * The definitions starting here have to do with the virtual scrolling + * region view into the addressbooks. That is, the display. + * + * We could make every use of an AdrBk_Entry go through a function call + * like adrbk_get_ae(). Instead, we try to be smart and avoid the extra + * function calls by knowing when the addrbook entry is still valid, either + * because we haven't called any functions that could invalidate it or because + * we have locked it in the cache. If we do lock it, we need to be careful + * that it eventually gets unlocked. That can be done by an explicit + * adrbk_get_ae(Unlock) call, or it is done implicitly when the address book + * is written out. The reason it can get invalidated is that the abe that + * we get returned to us is just a pointer to a cached addrbook entry, and + * that entry can be flushed from the cache by other addrbook activity. + * So we need to be careful to make sure the abe is certain to be valid + * before using it. + * + * Data structures for the display of the address book. There's one + * of these structures per line on the screen. + * + * Types: Title -- The title line for the different address books. It has + * a ptr to the text of the Title line. + * ClickHereCmb -- This is the line that says to click here to + * expand. It changes types into the individual expanded + * components once it is expanded. It doesn't have any data + * other than an implicit title. This is only used with the + * combined-style addrbook display. + * ListClickHere --This is the line that says to click here to + * expand the members of a distribution list. It changes + * types into the individual expanded ListEnt's (if any) + * when it is expanded. It has a ptr to an AdrBk_Entry. + * ListEmpty -- Line that says this is an empty distribution list. No data. + * Empty -- Line that says this is an empty addressbook. No data. + * ZoomEmpty -- Line that says no addrs in zoomed view. No data. + * AddFirstGLob -- Place holder for adding an abook. No data. + * AddFirstPers -- Place holder for adding an abook. No data. + * DirServers -- Place holder for accessing directory servers. No data. + * Simple -- A single addressbook entry. It has a ptr to an AdrBk_Entry. + * When it is displayed, the fields are usually: + * <nickname> <fullname> <address or another nic> + * ListHead -- The head of an address list. This has a ptr to an + * AdrBk_Entry. + * <blank line> followed by + * <nickname> <fullname> "DISTRIBUTION LIST:" + * ListEnt -- The rest of an address list. It has a pointer to its + * ListHead element and a ptr (other) to this specific address + * (not a ptr to another AdrBk_Entry). + * <blank> <blank> <address or another nic> + * Text -- A ptr to text. For example, the ----- lines and + * whitespace lines. + * NoAbooks -- There are no address books at all. + * Beginnning -- The (imaginary) elements before the first real element + * End -- The (imaginary) elements after the last real element + */ +typedef enum {DlNotSet, Empty, ZoomEmpty, AddFirstPers, AddFirstGlob, + AskServer, Title, Simple, ListHead, ListClickHere, + ListEmpty, ListEnt, Text, Beginning, End, NoAbooks, + ClickHereCmb, TitleCmb} LineType; +/* each line of address book display is one of these structures */ +typedef struct addrscrn_disp { + union { + struct { + adrbk_cntr_t ab_element_number; /* which addrbook entry */ + adrbk_cntr_t ab_list_offset; /* which member of the list */ + }addrbook_entry; + char *text_ptr; /* a UTF-8 string */ + }union_to_save_space; + LineType type; +} AddrScrn_Disp; +#define usst union_to_save_space.text_ptr +#define elnum union_to_save_space.addrbook_entry.ab_element_number +#define l_offset union_to_save_space.addrbook_entry.ab_list_offset + +#define entry_is_checked exp_is_expanded +#define entry_get_next exp_get_next +#define entry_set_checked exp_set_expanded +#define entry_unset_checked exp_unset_expanded +#define any_checked exp_any_expanded +#define howmany_checked exp_howmany_expanded + +#define entry_is_selected exp_is_expanded +#define entry_set_selected exp_set_expanded +#define entry_unset_selected exp_unset_expanded +#define any_selected exp_any_expanded +#define howmany_selected exp_howmany_expanded + +#define entry_is_deleted exp_is_expanded +#define entry_set_deleted exp_set_expanded +#define howmany_deleted exp_howmany_expanded + +#define entry_is_added exp_is_expanded +#define entry_set_added exp_set_expanded + +/* + * Argument to expand_address and build_address_internal is a BuildTo, + * which is either a char * address or an AdrBk_Entry * (if we have already + * looked it up in an addrbook). + */ +typedef enum {Str, Abe} Build_To_Arg_Type; +typedef struct build_to { + Build_To_Arg_Type type; + union { + char *str; /* normal looking address string */ + AdrBk_Entry *abe; /* addrbook entry */ + }arg; +} BuildTo; + + +/* Display lines used up by each top-level addrbook, counting blanks */ +#define LINES_PER_ABOOK (3) +/* How many of those lines are visible (not blank) */ +#define VIS_LINES_PER_ABOOK (2) +/* How many extra lines are between the personal and global sections */ +#define XTRA_LINES_BETWEEN (1) +/* How many lines does the PerAdd line take, counting blank line */ +#define LINES_PER_ADD_LINE (2) +/* Extra title lines above first entry that are shown when the combined-style + display is turned on. */ +#define XTRA_TITLE_LINES_IN_OLD_ABOOK_DISP (4) + +typedef enum {DlcNotSet, + DlcPersAdd, /* config screen only */ + DlcGlobAdd, /* " " " */ + + DlcTitle, /* top level displays */ + DlcTitleNoPerm, /* " " " */ + DlcSubTitle, /* " " " */ + DlcTitleBlankTop, /* " " " */ + DlcGlobDelim1, /* " " " */ + DlcGlobDelim2, /* " " " */ + DlcDirDelim1, /* " " " */ + DlcDirDelim2, /* " " " */ + DlcDirAccess, /* " " " */ + DlcDirSubTitle, /* " " " */ + DlcDirBlankTop, /* " " " */ + + DlcTitleDashTopCmb, /* combined-style top level display */ + DlcTitleCmb, /* " " " " " */ + DlcTitleDashBottomCmb, /* " " " " " */ + DlcTitleBlankBottomCmb, /* " " " " " */ + DlcClickHereCmb, /* " " " " " */ + DlcTitleBlankTopCmb, /* " " " " " */ + DlcDirDelim1a, /* " " " " " */ + DlcDirDelim1b, /* " " " " " */ + DlcDirDelim1c, /* " " " " " */ + + DlcEmpty, /* display of a single address book */ + DlcZoomEmpty, /* " */ + DlcNoPermission, /* " */ + DlcSimple, /* " */ + DlcListHead, /* " */ + DlcListClickHere, /* " */ + DlcListEmpty, /* " */ + DlcListEnt, /* " */ + DlcListBlankTop, /* " */ + DlcListBlankBottom, /* " */ + DlcNoAbooks, /* " */ + + DlcOneBeforeBeginning, /* used in both */ + DlcTwoBeforeBeginning, /* " " " */ + DlcBeginning, /* " " " */ + DlcEnd} DlCacheType; + +typedef enum {Initialize, FirstEntry, LastEntry, ArbitraryStartingPoint, + DoneWithCache, FlushDlcFromCache, Lookup} DlMgrOps; +typedef enum {Warp, DontWarp} HyperType; + +/* + * The DlCacheTypes are the types that a dlcache element can be labeled. + * The idea is that there needs to be enough information in the single + * cache element by itself so that you can figure out what the next and + * previous dl rows are by just knowing this one row. + * + * In the top-level display, there are DlcTitle lines or DlcTitleNoPerm + * lines, which are the same except we know that we can't access the + * address book in the latter case. DlcSubTitle lines follow each of the + * types of Title lines, and Titles within a section are separated by + * DlcTitleBlankTop lines, which belong to (have the same adrbk_num as) + * the Title they are above. + * If there are no address books and no directory servers defined, we + * have a DlcNoAbooks line. When we are displaying an individual address + * book (not in the top-level display) there is another set of types. An + * empty address book consists of one line of type DlcEmpty. An address + * book without read permission is a DlcNoPermission. Simple address book + * entries consist of a single DlcSimple line. Lists begin with a + * DlcListHead. If the list is not expanded the DlcListHead is followed by + * a DlcListClickHere. If it is known to be a list with no members the + * DlcListHead is followed by a DlcListEmpty. If there are members and + * the list is expanded, each list member is a single line of type + * DlcListEnt. Two lists are separated by a DlcListBlankBottom belonging + * to the first list. A list followed or preceded by a DlcSimple address + * row has a DlcListBlank(Top or Bottom) separating it from the + * DlcSimple. Above the top row of the display is an imaginary line of + * type DlcOneBeforeBeginning. Before that is a DlcTwoBeforeBeginning. And + * before that all the lines are just DlcBeginning lines. After the last + * display line is a DlcEnd. + * + * The DlcDirAccess's are indexed by adrbk_num (re-used for this). + * Adrbk_num -1 means access all of the servers. + * Adrbk_num 0 ... n_serv -1 means access all a particular server. + * Adrbk_num n_serv means access as if from composer using config setup. + * + * Here are the types of lines and where they fall in the top-level display: + * + * (not a visible line) DlcBeginning + * (not a visible line) DlcBeginning + * (not a visible line) DlcTwoBeforeBeginning + * (not a visible line) DlcOneBeforeBeginning + * Title DlcTitle (or TitleNoPerm) + * Subtitle DlcSubTitle + * ---this is blank---------------- DlcTitleBlankTop + * Title DlcTitle (or TitleNoPerm) + * Subtitle DlcSubTitle + * ---this is blank---------------- DlcGlobDelim1 + * ---this is blank---------------- DlcGlobDelim2 + * Title DlcTitle (or TitleNoPerm) + * Subtitle DlcSubTitle + * ---this is blank---------------- DlcTitleBlankTop + * Title DlcTitle (or TitleNoPerm) + * Subtitle DlcSubTitle + * ---this is blank---------------- DlcDirDelim1 + * ---this is blank---------------- DlcDirDelim2 + * Directory (query server 1) DlcDirAccess (adrbk_num 0) + * Subtitle DlcDirSubTitle (adrbk_num 0) + * ---this is blank---------------- DlcDirBlankTop + * Directory (query server 2) DlcDirAccess (adrbk_num 1) + * Subtitle DlcDirSubTitle (adrbk_num 1) + * (not a visible line) DlcEnd + * (not a visible line) DlcEnd + * + * + * There is a combined-style display triggered by the F_CMBND_ABOOK_DISP + * feature. It's a mixture of the top-level and open addrbook displays. When an + * addrbook is opened the rest of the addrbooks don't disappear from the + * screen. In this view, the ClickHere lines can be replaced with the entire + * contents of the addrbook, but the other stuff remains on the screen, too. + * Here are the types of lines and where they fall in the + * combined-style display: + * + * (not a visible line) DlcBeginning + * (not a visible line) DlcBeginning + * (not a visible line) DlcTwoBeforeBeginning + * (not a visible line) DlcOneBeforeBeginning + * -------------------------------- DlcTitleDashTopOld + * Title DlcTitleOld + * -------------------------------- DlcTitleDashBottomOld + * ---this is blank---------------- DlcTitleBlankBottom + * ClickHere DlcClickHereOld + * ---this is blank---------------- DlcTitleBlankTop + * -------------------------------- DlcTitleDashTopOld + * Title DlcTitleOld + * -------------------------------- DlcTitleDashBottomOld + * ---this is blank---------------- DlcTitleBlankBottom + * ClickHere DlcClickHereOld + * ---this is blank---------------- DlcDirDelim1 + * -------------------------------- DlcDirDelim1a + * Directories DlcDirDelim1b + * -------------------------------- DlcDirDelim1c + * ---this is blank---------------- DlcDirDelim2 + * Directory (query server 1) DlcDirAccess (adrbk_num 0) + * Subtitle DlcDirSubTitle (adrbk_num 0) + * ---this is blank---------------- DlcDirBlankTop + * Directory (query server 2) DlcDirAccess (adrbk_num 1) + * Subtitle DlcDirSubTitle (adrbk_num 1) + * (not a visible line) DlcEnd + * (not a visible line) DlcEnd + * + * If there are no addrbooks in either of the two sections, or no Directory + * servers, then that section is left out of the display. If there is only + * one address book and no Directories, then the user goes directly into the + * single addressbook view which looks like: + * + * if(no entries in addrbook) + * + * (not a visible line) DlcBeginning + * (not a visible line) DlcBeginning + * (not a visible line) DlcTwoBeforeBeginning + * (not a visible line) DlcOneBeforeBeginning + * Empty or NoPerm or NoAbooks DlcEmpty, DlcZoomEmpty, DlcNoPermission, + * or DlcNoAbooks + * (not a visible line) DlcEnd + * (not a visible line) DlcEnd + * + * else + * + * (not a visible line) DlcBeginning + * (not a visible line) DlcBeginning + * (not a visible line) DlcTwoBeforeBeginning + * (not a visible line) DlcOneBeforeBeginning + * Simple Entry DlcSimple + * Simple Entry DlcSimple + * Simple Entry DlcSimple + * DlcListBlankTop + * List Header DlcListHead + * Unexpanded List DlcListClickHere + * or + * Empty List DlcListEmpty + * or + * List Entry 1 DlcListEnt + * List Entry 2 DlcListEnt + * DlcListBlankBottom + * List Header DlcListHead + * List Entry 1 DlcListEnt + * List Entry 2 DlcListEnt + * List Entry 3 DlcListEnt + * DlcListBlankBottom + * Simple Entry DlcSimple + * DlcListBlankTop + * List Header DlcListHead + * Unexpanded List DlcListClickHere + * (not a visible line) DlcEnd + * (not a visible line) DlcEnd + * + * The config screen view is similar to the top-level view except there + * is no directory section (it has it's own config screen) and if there + * are zero personal addrbooks or zero global addrbooks then a placeholder + * line of type DlcPersAdd or DlcGlobAdd takes the place of the DlcTitle + * line. + */ +typedef struct dl_cache { + long global_row; /* disp_list row number */ + adrbk_cntr_t dlcelnum; /* which elnum from that addrbook */ + adrbk_cntr_t dlcoffset; /* offset in a list, only for ListEnt rows */ + short adrbk_num; /* which address book we're related to */ + DlCacheType type; /* type of this row */ + AddrScrn_Disp dl; /* the actual dl that goes with this row */ +} DL_CACHE_S; + + +typedef enum {Nickname, Fullname, Addr, Filecopy, Comment, Notused, + Def, WhenNoAddrDisplayed, Checkbox, Selected} ColumnType; + +/* + * Users can customize the addrbook display, so this tells us which data + * is in a particular column and how wide the column is. There is an + * array of these per addrbook, of length NFIELDS (number of possible cols). + */ +typedef struct column_description { + ColumnType type; + WidthType wtype; + int req_width; /* requested width (for fixed and percent types) */ + int width; /* actual width to use */ + int old_width; +} COL_S; + + +/* address book attributes for peraddrbook type */ +#define GLOBAL 0x1 /* else it is personal */ +#define REMOTE_VIA_IMAP 0x2 /* else it is a local file */ + + +typedef enum {TotallyClosed, /* hash tables not even set up yet */ + Closed, /* data not read in, no display list */ + NoDisplay, /* data is accessible, no display list */ + HalfOpen, /* data not accessible, initial display list is set */ + ThreeQuartOpen, /* like HalfOpen without partial_close */ + Open /* data is accessible and display list is set */ + } OpenStatus; + +/* + * There is one of these per addressbook. + */ +typedef struct peraddrbook { + unsigned type; + AccessType access; + OpenStatus ostatus; + char *abnick, /* kept internally in UTF-8 */ + *filename; + AdrBk *address_book; /* the address book handle */ + int gave_parse_warnings; + COL_S disp_form[NFIELDS]; /* display format */ + int nick_is_displayed; /* these are for convenient, */ + int full_is_displayed; /* fast access. Could get */ + int addr_is_displayed; /* same info from disp_form. */ + int fcc_is_displayed; + int comment_is_displayed; + STORE_S *so; /* storage obj for addrbook + temporarily stored here */ +} PerAddrBook; + + +/* + * This keeps track of the state of the screen and information about all + * the address books. We usually only have one of these but sometimes + * we save a version of this state (with save_state) and re-call the + * address book functions. Then when we pop back up to where we were + * (with restore_state) the screen and the state of the address books + * is restored to what it was. + */ +typedef struct addrscreenstate { + PerAddrBook *adrbks; /* array of addrbooks */ + int initialized, /* have we done at least simple init? */ + n_addrbk, /* how many addrbooks are there */ + how_many_personals, /* how many of those are personal? */ + cur, /* current addrbook */ + cur_row, /* currently selected line */ + old_cur_row, /* previously selected line */ + l_p_page; /* lines per (screen) page */ + long top_ent; /* index in disp_list of top entry on screen */ + int ro_warning, /* whether or not to give warning */ + checkboxes, /* whether or not to display checkboxes */ + selections, /* whether or not to display selections */ + do_bold, /* display selections in bold */ + no_op_possbl, /* user can't do anything with current conf */ + zoomed, /* zoomed into view only selected entries */ + config, /* called from config screen */ + n_serv, /* how many directory servers are there */ + n_impl; /* how many of those have impl bit set */ +#ifdef _WINDOWS + long last_ent; /* index of last known entry */ +#endif +} AddrScrState; + + +/* + * AddrBookScreen and AddrBookConfig are the maintenance screens, all the + * others are selection screens. The AddrBookConfig screen is an entry + * point from the Setup/Addressbooks command in the main menu. Those that + * end in Com are called from the pico HeaderEditor, either while in the + * composer or while editing an address book entry. SelectManyNicks + * returns a comma-separated list of nicknames. SelectAddrLccCom and + * SelectNicksCom return a comma-separated list of nicknames. + * SelectNickTake, SelectNickCom, and SelectNick all return a single + * nickname. The ones that returns multiple nicknames or multiple + * addresses all allow ListMode. They are SelectAddrLccCom, + * SelectNicksCom, and SelectMultNoFull. + */ +typedef enum {AddrBookScreen, /* maintenance screen */ + AddrBookConfig, /* config screen */ + SelectAddrLccCom, /* returns list of nicknames of lists */ + SelectNicksCom, /* just like SelectAddrLccCom, but allows + selecting simple *and* list entries */ + SelectNick, /* returns single nickname */ + SelectNickTake, /* Same as SelectNick but different help */ + SelectNickCom, /* Same as SelectNick but from composer */ + SelectManyNicks, /* Returns list of nicks */ + SelectAddr, /* Returns single address */ + SelectAddrNoFull, /* Returns single address without fullname */ + SelectMultNoFull /* Returns mult addresses without fullname */ + } AddrBookArg; + + +typedef struct save_state_struct { + AddrScrState *savep; + OpenStatus *stp; + DL_CACHE_S *dlc_to_warp_to; +} SAVE_STATE_S; + + +typedef struct act_list { + PerAddrBook *pab; + adrbk_cntr_t num, + num_in_dst; + unsigned int skip:1, + dup:1; +} ACTION_LIST_S; + + +typedef struct ta_abook_state { + PerAddrBook *pab; + SAVE_STATE_S state; +} TA_STATE_S; + + +/* + * Many of these should really only have a single value but we give them + * an array for uniformity. + */ +typedef struct _vcard_info { + char **nickname; + char **fullname; + char *first; + char *middle; + char *last; + char **fcc; + char **note; + char **title; + char **tel; + char **email; +} VCARD_INFO_S; + + +extern AddrScrState as; +extern jmp_buf addrbook_changed_unexpectedly; +extern long msgno_for_pico_callback; +extern BODY *body_for_pico_callback; +extern ENVELOPE *env_for_pico_callback; +extern int ab_nesting_level; + + +/* + * These constants are supposed to be suitable for use as longs where the longs + * are representing a line number or message number. + * These constants aren't suitable for use with type adrbk_cntr_t. There is + * a constant called NO_NEXT which you probably want for that. + */ +#define NO_LINE (2147483645L) +#define CHANGED_CURRENT (NO_LINE + 1L) + + +/* + * The do-while stuff is so these are statements and can be written with + * a following ; like a regular statement without worrying about braces and all. + */ +#define SKIP_SPACE(p) do{while(*p && *p == SPACE)p++;}while(0) +#define SKIP_TO_TAB(p) do{while(*p && *p != TAB)p++;}while(0) +#define RM_END_SPACE(start,end) \ + do{char *_ptr = end; \ + while(--_ptr >= start && *_ptr == SPACE)*_ptr = '\0';}while(0) +#define REPLACE_NEWLINES_WITH_SPACE(p) \ + do{register char *_qq; \ + for(_qq = p; *_qq; _qq++) \ + if(*_qq == '\n' || *_qq == '\r') \ + *_qq = SPACE;}while(0) +#define DELETED "#DELETED-" +#define DELETED_LEN 9 + + +#define ONE_HUNDRED_DAYS (60L * 60L * 24L * 100L) + +/* + * When address book entries are deleted, they are left in the file + * with the nickname prepended with a string like #DELETED-96/01/25#, + * which stands for year 96, month 1, day 25 of the month. When one of + * these entries is more than ABOOK_DELETED_EXPIRE_TIME seconds old, + * then it will be totally removed from the address book the next time + * an adrbk_write() is done. This is for emergencies where somebody + * deletes something from their address book and would like to get it + * back. You get it back by editing the nickname field manually to remove + * the extra 18 characters off the front. + */ +#ifndef ABOOK_DELETED_EXPIRE_TIME +#define ABOOK_DELETED_EXPIRE_TIME ONE_HUNDRED_DAYS +#endif + + +#ifdef ENABLE_LDAP +typedef struct _cust_filt { + char *filt; + int combine; +} CUSTOM_FILT_S; + +#define RUN_LDAP "LDAP: " +#define LEN_RL 6 +#define QRUN_LDAP "\"LDAP: " +#define LEN_QRL 7 +#define LDAP_DISP "[ LDAP Lookup ]" +#endif + + +/* + * There are no restrictions on the length of any of the fields, except that + * there are some restrictions in the current input routines. + */ + +/* + * The on-disk address book has entries that look like: + * + * Nickname TAB Fullname TAB Address_Field TAB Fcc TAB Comment + * + * An entry may be broken over more than one line but only at certain + * spots. A continuation line starts with spaces (spaces, not white space). + * One place a line break can occur is after any of the TABs. The other + * place is in the middle of a list of addresses, between addresses. + * The Address_Field may be either a simple address without the fullname + * or brackets, or it may be an address list. An address list is + * distinguished by the fact that it begins with "(" and ends with ")". + * Addresses within a list are comma separated and each address in the list + * may be a full rfc822 address, including Fullname and so on. + * + * Examples: + * fred TAB Flintstone, Fred TAB fred@bedrock.net TAB fcc-flintstone TAB comment + * or + * fred TAB Flintstone, Fred TAB \n + * fred@bedrock.net TAB fcc-flintstone TAB \n + * comment + * somelist TAB Some List TAB (fred, \n + * Barney Rubble <barney@bedrock.net>, wilma@bedrock.net) TAB \n + * fcc-for-some-list TAB comment + */ + + +/* exported prototypes */ +AdrBk *adrbk_open(PerAddrBook *, char *, char *, size_t, int); +int adrbk_is_in_sort_order(AdrBk *, int); +adrbk_cntr_t adrbk_count(AdrBk *); +AdrBk_Entry *adrbk_get_ae(AdrBk *, a_c_arg_t); +AdrBk_Entry *adrbk_lookup_by_nick(AdrBk *, char *, adrbk_cntr_t *); +AdrBk_Entry *adrbk_lookup_by_addr(AdrBk *, char *, adrbk_cntr_t *); +char *adrbk_formatname(char *, char **, char **); +void adrbk_clearrefs(AdrBk *); +AdrBk_Entry *adrbk_newentry(void); +AdrBk_Entry *copy_ae(AdrBk_Entry *); +int adrbk_add(AdrBk *, a_c_arg_t, char *, char *, char *, char *, + char *, Tag, adrbk_cntr_t *, int *, int, int, int); +int adrbk_append(AdrBk *, char *, char *, char *, + char *, char *, Tag, adrbk_cntr_t *); +int adrbk_delete(AdrBk *, a_c_arg_t, int, int, int, int); +int adrbk_listdel(AdrBk *, a_c_arg_t, char *); +int adrbk_listdel_all(AdrBk *, a_c_arg_t); +int adrbk_nlistadd(AdrBk *, a_c_arg_t,adrbk_cntr_t *,int *,char **,int,int,int); +void adrbk_check_validity(AdrBk *, long); +MAILSTREAM *adrbk_handy_stream(char *); +void adrbk_close(AdrBk *); +void adrbk_partial_close(AdrBk *); +void note_closed_adrbk_stream(MAILSTREAM *); +int adrbk_write(AdrBk *, a_c_arg_t, adrbk_cntr_t *, int *, int, int); +void free_ae(AdrBk_Entry **); +void exp_free(EXPANDED_S *); +int exp_is_expanded(EXPANDED_S *, a_c_arg_t); +int exp_howmany_expanded(EXPANDED_S *); +int exp_any_expanded(EXPANDED_S *); +adrbk_cntr_t exp_get_next(EXPANDED_S **); +void exp_set_expanded(EXPANDED_S *, a_c_arg_t); +void exp_unset_expanded(EXPANDED_S *, a_c_arg_t); +int adrbk_sort(AdrBk *, a_c_arg_t, adrbk_cntr_t *, int); +int any_ab_open(void); +void init_ab_if_needed(void); +int init_addrbooks(OpenStatus, int, int, int); +void addrbook_reset(void); +void addrbook_redo_sorts(void); +AccessType adrbk_access(PerAddrBook *); +void trim_remote_adrbks(void); +void completely_done_with_adrbks(void); +void init_abook(PerAddrBook *, OpenStatus); +int adrbk_check_all_validity_now(void); +int adrbk_check_and_fix(PerAddrBook *, int, int, int); +int adrbk_check_and_fix_all(int, int, int); +void adrbk_maintenance(void); +char **parse_addrlist(char *); +char *skip_to_next_addr(char *); +void add_forced_entries(AdrBk *); + + +#endif /* PITH_ADRBKLIB_INCLUDED */ |