* For mailing lists, Alpine adds a description of the type of link
[alpine.git] / pith / adrbklib.h
blob38e5bf79a2abc8b678aab200d985ab318e0cdf47
1 /*
2 * $Id: adrbklib.h 1012 2008-03-26 00:44:22Z hubert@u.washington.edu $
4 * ========================================================================
5 * Copyright 2006-2008 University of Washington
6 * Copyright 2013-2022 Eduardo Chappa
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * ========================================================================
17 #ifndef PITH_ADRBKLIB_INCLUDED
18 #define PITH_ADRBKLIB_INCLUDED
21 #include "../pith/indxtype.h"
22 #include "../pith/remtype.h"
23 #include "../pith/store.h"
24 #include "../pith/string.h"
28 * Some notes:
30 * The order that the address book is stored in on disk is the order that
31 * the entries will be displayed in. When an address book is opened,
32 * if it is ReadWrite the sort order is checked and it is sorted if it is
33 * out of order.
35 * Considerable complexity that previously existed in the address book
36 * code has been removed. Cpu speeds have improved significantly and
37 * memory has increased dramatically, as well. The cost of the complexity
38 * of the lookup file and hashtables and all that stuff is thought to be
39 * more than the benefits. See pre-5.00 pine adrbklib.h for the way it
40 * used to be.
42 * The display code has remained the same.
43 * There is also some allocation happening
44 * in addrbook.c. In particular, the display is a window into an array
45 * of rows, at least one row per addrbook entry plus more for lists.
46 * Each row is an AddrScrn_Disp structure and those should typically take
47 * up 6 or 8 bytes. A cached copy of addrbook entries is not kept, just
48 * the element number to look it up (and often get it out of the EntryRef
49 * cache). In order to avoid having to allocate all those rows, this is
50 * also in the form of a cache. Only 3 * screen_length rows are kept in
51 * the cache, and the cache is always a simple interval of rows. That is,
52 * rows between valid_low and valid_high are all in the cache. Row numbers
53 * in the display list are a little mysterious. There is no origin. That
54 * is, you don't necessarily know where the start or end of the display
55 * is. You only know how to go forward and backward and how to "warp"
56 * to new locations in the display and go forward and backward from there.
57 * This is because we don't know how many rows there are all together. It
58 * is also a way to avoid searching through everything to get somewhere.
59 * If you want to go to the End, you warp there and start backwards instead
60 * of reading through all the entries to get there. If you edit an entry
61 * so that it sorts into a new location, you warp to that new location to
62 * save processing all of the entries in between.
65 * Notes about RFC1522 encoding:
67 * If the fullname field contains other than US-ASCII characters, it is
68 * encoded using the rules of RFC1522 or its successor. The value actually
69 * stored in the file is encoded, even if it matches the character set of
70 * the user. This is so it is easy to pass the entry around or to change
71 * character sets without invalidating entries in the address book. When
72 * a fullname is displayed, it is first decoded. If the fullname field is
73 * encoded as being from a character set other than the user's character
74 * set, that will be retained until the user edits the field. Then it will
75 * change over to the user's character set. The comment field works in
76 * the same way, as do the "phrase" fields of any addresses. On outgoing
77 * mail, the correct character set will be retained if you use ComposeTo
78 * from the address book screen. However, if you use a nickname from the
79 * composer or ^T from the composer, the character set will be lost if it
80 * is different from the user's character set.
83 * Notes about RemoteViaImap address books:
85 * There are currently two types of address books, Local and Imap. Local means
86 * it is in a local file. Imap means it is stored in a folder on a remote
87 * IMAP server. The folder is a regular folder containing mail messages but
88 * the messages are special. The first message is a header message. The last
89 * message is the address book data. In between messages are old versions of
90 * the address book data. The address book data is stored in the message as
91 * it would be on disk, with no fancy mime encoding or anything. When it is
92 * used the data from the last message in the folder is copied to a local file
93 * and then it is used just like a local file. The local file is a cache for
94 * the remote data. We can tell the remote data has been changed by looking
95 * at the Date of the last message in the remote folder. If we see it has
96 * changed we copy the whole file over again and replace the cache file.
97 * A possibly quicker way to tell if it has changed is if the UID has
98 * changed or the number of messages in the folder has changed. We use those
99 * methods if possible since they don't require opening a new stream and
100 * selecting the folder. There is one metadata file for address book data.
101 * The name of that file is stored in the pinerc file. It contains the names
102 * of the cache files for RemoveViaImap address books plus other caching
103 * information for those address books (uid...).
106 #define NFIELDS 11 /* one more than num of data fields in addrbook entry */
109 * The type a_c_arg_t is a little confusing. It's the type we use in
110 * place of adrbk_cntr_t when we want to pass an adrbk_cntr_t in an argument.
111 * We were running into problems with the integral promotion of adrbk_cntr_t
112 * args. A_c_arg_t has to be large enough to hold a promoted adrbk_cntr_t.
113 * So, if adrbk_cntr_t is unsigned short, then a_c_arg_t needs to be int if
114 * int is larger than short, or unsigned int if short is same size as int.
115 * Since usign16_t always fits in a short, a_c_arg_t of unsigned int should
116 * always work for !HUGE. For HUGE, UINT32 will be either an unsigned int
117 * or an unsigned long. If it is an unsigned long, then a_c_arg_t better be
118 * an unsigned long, too. If it is an unsigned int, then a_c_arg_t could
119 * be an unsigned int, too. However, if we just make it unsigned long, then
120 * it will be the same in all cases and big enough in all cases.
121 * For most people SUINT32 is UINT32, but users can define at configure stage
122 * that SUINT32 could be something different, by means of defining an environment
123 * variable SUINT32 as, say, unsigned long.
126 #define adrbk_cntr_t SUINT32 /* addrbook counter type */
127 typedef unsigned long a_c_arg_t; /* type of arg passed for adrbk_cntr_t */
128 #define NO_NEXT ((adrbk_cntr_t)-1)
129 #define MAX_ADRBK_SIZE (2000000000L) /* leave room for extra display lines */
132 * The value NO_NEXT is reserved to mean that there is no next address, or that
133 * there is no address number to return. This is similar to getc returning
134 * -1 when there is no char to get, but since we've defined this to be
135 * unsigned we need to reserve one of the valid values for this purpose.
136 * With current implementation it needs to be all 1's, so memset initialization
137 * will work correctly.
140 typedef enum {NotSet, Single, List} Tag;
143 /* This is what is actually used by the routines that manipulate things */
144 typedef struct adrbk_entry {
145 char *nickname; /* UTF-8 */
146 char *fullname; /* of simple addr or list (stored in UTF-8) */
147 union addr {
148 char *addr; /* for simple Single entries */
149 char **list; /* for distribution lists */
150 } addr;
151 char *fcc; /* fcc specific for when sending to this address */
152 char *extra; /* comments field (stored in UTF-8) */
153 char referenced; /* for detecting loops during lookup */
154 Tag tag; /* single addr (Single) or a list (List) */
155 } AdrBk_Entry;
158 typedef struct abook_tree_node {
159 struct abook_tree_node *down; /* next letter of nickname */
160 struct abook_tree_node *right; /* alternate letter of nickname */
161 char value; /* character at this node */
162 adrbk_cntr_t entrynum; /* use NO_NEXT as no-data indicator */
163 } AdrBk_Trie;
166 /* information useful for displaying the addrbook */
167 typedef struct width_stuff {
168 int max_nickname_width;
169 int max_fullname_width;
170 int max_addrfield_width;
171 int max_fccfield_width;
172 int third_biggest_fullname_width;
173 int third_biggest_addrfield_width;
174 int third_biggest_fccfield_width;
175 } WIDTH_INFO_S;
178 typedef struct expanded_list {
179 adrbk_cntr_t ent;
180 struct expanded_list *next;
181 } EXPANDED_S;
184 typedef enum {Local, Imap} AdrbkType;
187 #ifndef IMAP_IDLE_TIMEOUT
188 #define IMAP_IDLE_TIMEOUT (10L * 60L) /* seconds */
189 #endif
190 #ifndef FILE_VALID_CHK_INTERVAL
191 #define FILE_VALID_CHK_INTERVAL ( 15L) /* seconds */
192 #endif
193 #ifndef LOW_FREQ_CHK_INTERVAL
194 #define LOW_FREQ_CHK_INTERVAL (240) /* minutes */
195 #endif
197 typedef struct adrbk {
198 AdrbkType type; /* type of address book */
199 char *orig_filename; /* passed in filename */
200 char *filename; /* addrbook filename */
201 char *our_filecopy; /* session copy of filename contents */
202 FILE *fp; /* fp for our_filecopy */
203 adrbk_cntr_t count; /* how many entries in addrbook */
204 adrbk_cntr_t del_count; /* how many #DELETED entries in abook */
205 AdrBk_Entry *arr; /* array of entries */
206 AdrBk_Entry *del; /* array of deleted entries */
207 AdrBk_Trie *nick_trie;
208 AdrBk_Trie *addr_trie;
209 AdrBk_Trie *full_trie;
210 AdrBk_Trie *revfull_trie;
211 time_t last_change_we_know_about;/* to look for others changing it*/
212 time_t last_local_valid_chk;/* when valid check was done */
213 unsigned flags; /* see defines in alpine.h (DEL_FILE...)*/
214 WIDTH_INFO_S widths; /* helps addrbook.c format columns */
215 int sort_rule;
216 EXPANDED_S *exp; /* this is for addrbook.c to use. A
217 list of expanded list entry nums is kept here */
218 EXPANDED_S *checks; /* this is for addrbook.c to use. A
219 list of checked entry nums is kept here */
220 EXPANDED_S *selects; /* this is for addrbook.c to use. A
221 list of selected entry nums is kept here */
222 REMDATA_S *rd;
223 } AdrBk;
227 * The definitions starting here have to do with the virtual scrolling
228 * region view into the addressbooks. That is, the display.
230 * We could make every use of an AdrBk_Entry go through a function call
231 * like adrbk_get_ae(). Instead, we try to be smart and avoid the extra
232 * function calls by knowing when the addrbook entry is still valid, either
233 * because we haven't called any functions that could invalidate it or because
234 * we have locked it in the cache. If we do lock it, we need to be careful
235 * that it eventually gets unlocked. That can be done by an explicit
236 * adrbk_get_ae(Unlock) call, or it is done implicitly when the address book
237 * is written out. The reason it can get invalidated is that the abe that
238 * we get returned to us is just a pointer to a cached addrbook entry, and
239 * that entry can be flushed from the cache by other addrbook activity.
240 * So we need to be careful to make sure the abe is certain to be valid
241 * before using it.
243 * Data structures for the display of the address book. There's one
244 * of these structures per line on the screen.
246 * Types: Title -- The title line for the different address books. It has
247 * a ptr to the text of the Title line.
248 * ClickHereCmb -- This is the line that says to click here to
249 * expand. It changes types into the individual expanded
250 * components once it is expanded. It doesn't have any data
251 * other than an implicit title. This is only used with the
252 * combined-style addrbook display.
253 * ListClickHere --This is the line that says to click here to
254 * expand the members of a distribution list. It changes
255 * types into the individual expanded ListEnt's (if any)
256 * when it is expanded. It has a ptr to an AdrBk_Entry.
257 * ListEmpty -- Line that says this is an empty distribution list. No data.
258 * Empty -- Line that says this is an empty addressbook. No data.
259 * ZoomEmpty -- Line that says no addrs in zoomed view. No data.
260 * AddFirstGLob -- Place holder for adding an abook. No data.
261 * AddFirstPers -- Place holder for adding an abook. No data.
262 * DirServers -- Place holder for accessing directory servers. No data.
263 * Simple -- A single addressbook entry. It has a ptr to an AdrBk_Entry.
264 * When it is displayed, the fields are usually:
265 * <nickname> <fullname> <address or another nic>
266 * ListHead -- The head of an address list. This has a ptr to an
267 * AdrBk_Entry.
268 * <blank line> followed by
269 * <nickname> <fullname> "DISTRIBUTION LIST:"
270 * ListEnt -- The rest of an address list. It has a pointer to its
271 * ListHead element and a ptr (other) to this specific address
272 * (not a ptr to another AdrBk_Entry).
273 * <blank> <blank> <address or another nic>
274 * Text -- A ptr to text. For example, the ----- lines and
275 * whitespace lines.
276 * NoAbooks -- There are no address books at all.
277 * Beginning -- The (imaginary) elements before the first real element
278 * End -- The (imaginary) elements after the last real element
280 typedef enum {DlNotSet, Empty, ZoomEmpty, AddFirstPers, AddFirstGlob,
281 AskServer, Title, Simple, ListHead, ListClickHere,
282 ListEmpty, ListEnt, Text, Beginning, End, NoAbooks,
283 ClickHereCmb, TitleCmb} LineType;
284 /* each line of address book display is one of these structures */
285 typedef struct addrscrn_disp {
286 union {
287 struct {
288 adrbk_cntr_t ab_element_number; /* which addrbook entry */
289 adrbk_cntr_t ab_list_offset; /* which member of the list */
290 }addrbook_entry;
291 char *text_ptr; /* a UTF-8 string */
292 }union_to_save_space;
293 LineType type;
294 } AddrScrn_Disp;
295 #define usst union_to_save_space.text_ptr
296 #define elnum union_to_save_space.addrbook_entry.ab_element_number
297 #define l_offset union_to_save_space.addrbook_entry.ab_list_offset
299 #define entry_is_checked exp_is_expanded
300 #define entry_get_next exp_get_next
301 #define entry_set_checked exp_set_expanded
302 #define entry_unset_checked exp_unset_expanded
303 #define any_checked exp_any_expanded
304 #define howmany_checked exp_howmany_expanded
306 #define entry_is_selected exp_is_expanded
307 #define entry_set_selected exp_set_expanded
308 #define entry_unset_selected exp_unset_expanded
309 #define any_selected exp_any_expanded
310 #define howmany_selected exp_howmany_expanded
312 #define entry_is_deleted exp_is_expanded
313 #define entry_set_deleted exp_set_expanded
314 #define howmany_deleted exp_howmany_expanded
316 #define entry_is_added exp_is_expanded
317 #define entry_set_added exp_set_expanded
320 * Argument to expand_address and build_address_internal is a BuildTo,
321 * which is either a char * address or an AdrBk_Entry * (if we have already
322 * looked it up in an addrbook).
324 typedef enum {Str, Abe} Build_To_Arg_Type;
325 typedef struct build_to {
326 Build_To_Arg_Type type;
327 union {
328 char *str; /* normal looking address string */
329 AdrBk_Entry *abe; /* addrbook entry */
330 }arg;
331 } BuildTo;
334 /* Display lines used up by each top-level addrbook, counting blanks */
335 #define LINES_PER_ABOOK (3)
336 /* How many of those lines are visible (not blank) */
337 #define VIS_LINES_PER_ABOOK (2)
338 /* How many extra lines are between the personal and global sections */
339 #define XTRA_LINES_BETWEEN (1)
340 /* How many lines does the PerAdd line take, counting blank line */
341 #define LINES_PER_ADD_LINE (2)
342 /* Extra title lines above first entry that are shown when the combined-style
343 display is turned on. */
344 #define XTRA_TITLE_LINES_IN_OLD_ABOOK_DISP (4)
346 typedef enum {DlcNotSet,
347 DlcPersAdd, /* config screen only */
348 DlcGlobAdd, /* " " " */
350 DlcTitle, /* top level displays */
351 DlcTitleNoPerm, /* " " " */
352 DlcSubTitle, /* " " " */
353 DlcTitleBlankTop, /* " " " */
354 DlcGlobDelim1, /* " " " */
355 DlcGlobDelim2, /* " " " */
356 DlcDirDelim1, /* " " " */
357 DlcDirDelim2, /* " " " */
358 DlcDirAccess, /* " " " */
359 DlcDirSubTitle, /* " " " */
360 DlcDirBlankTop, /* " " " */
362 DlcTitleDashTopCmb, /* combined-style top level display */
363 DlcTitleCmb, /* " " " " " */
364 DlcTitleDashBottomCmb, /* " " " " " */
365 DlcTitleBlankBottomCmb, /* " " " " " */
366 DlcClickHereCmb, /* " " " " " */
367 DlcTitleBlankTopCmb, /* " " " " " */
368 DlcDirDelim1a, /* " " " " " */
369 DlcDirDelim1b, /* " " " " " */
370 DlcDirDelim1c, /* " " " " " */
372 DlcEmpty, /* display of a single address book */
373 DlcZoomEmpty, /* " */
374 DlcNoPermission, /* " */
375 DlcSimple, /* " */
376 DlcListHead, /* " */
377 DlcListClickHere, /* " */
378 DlcListEmpty, /* " */
379 DlcListEnt, /* " */
380 DlcListBlankTop, /* " */
381 DlcListBlankBottom, /* " */
382 DlcNoAbooks, /* " */
384 DlcOneBeforeBeginning, /* used in both */
385 DlcTwoBeforeBeginning, /* " " " */
386 DlcBeginning, /* " " " */
387 DlcEnd} DlCacheType;
389 typedef enum {Initialize, FirstEntry, LastEntry, ArbitraryStartingPoint,
390 DoneWithCache, FlushDlcFromCache, Lookup} DlMgrOps;
391 typedef enum {Warp, DontWarp} HyperType;
394 * The DlCacheTypes are the types that a dlcache element can be labeled.
395 * The idea is that there needs to be enough information in the single
396 * cache element by itself so that you can figure out what the next and
397 * previous dl rows are by just knowing this one row.
399 * In the top-level display, there are DlcTitle lines or DlcTitleNoPerm
400 * lines, which are the same except we know that we can't access the
401 * address book in the latter case. DlcSubTitle lines follow each of the
402 * types of Title lines, and Titles within a section are separated by
403 * DlcTitleBlankTop lines, which belong to (have the same adrbk_num as)
404 * the Title they are above.
405 * If there are no address books and no directory servers defined, we
406 * have a DlcNoAbooks line. When we are displaying an individual address
407 * book (not in the top-level display) there is another set of types. An
408 * empty address book consists of one line of type DlcEmpty. An address
409 * book without read permission is a DlcNoPermission. Simple address book
410 * entries consist of a single DlcSimple line. Lists begin with a
411 * DlcListHead. If the list is not expanded the DlcListHead is followed by
412 * a DlcListClickHere. If it is known to be a list with no members the
413 * DlcListHead is followed by a DlcListEmpty. If there are members and
414 * the list is expanded, each list member is a single line of type
415 * DlcListEnt. Two lists are separated by a DlcListBlankBottom belonging
416 * to the first list. A list followed or preceded by a DlcSimple address
417 * row has a DlcListBlank(Top or Bottom) separating it from the
418 * DlcSimple. Above the top row of the display is an imaginary line of
419 * type DlcOneBeforeBeginning. Before that is a DlcTwoBeforeBeginning. And
420 * before that all the lines are just DlcBeginning lines. After the last
421 * display line is a DlcEnd.
423 * The DlcDirAccess's are indexed by adrbk_num (re-used for this).
424 * Adrbk_num -1 means access all of the servers.
425 * Adrbk_num 0 ... n_serv -1 means access all a particular server.
426 * Adrbk_num n_serv means access as if from composer using config setup.
428 * Here are the types of lines and where they fall in the top-level display:
430 * (not a visible line) DlcBeginning
431 * (not a visible line) DlcBeginning
432 * (not a visible line) DlcTwoBeforeBeginning
433 * (not a visible line) DlcOneBeforeBeginning
434 * Title DlcTitle (or TitleNoPerm)
435 * Subtitle DlcSubTitle
436 * ---this is blank---------------- DlcTitleBlankTop
437 * Title DlcTitle (or TitleNoPerm)
438 * Subtitle DlcSubTitle
439 * ---this is blank---------------- DlcGlobDelim1
440 * ---this is blank---------------- DlcGlobDelim2
441 * Title DlcTitle (or TitleNoPerm)
442 * Subtitle DlcSubTitle
443 * ---this is blank---------------- DlcTitleBlankTop
444 * Title DlcTitle (or TitleNoPerm)
445 * Subtitle DlcSubTitle
446 * ---this is blank---------------- DlcDirDelim1
447 * ---this is blank---------------- DlcDirDelim2
448 * Directory (query server 1) DlcDirAccess (adrbk_num 0)
449 * Subtitle DlcDirSubTitle (adrbk_num 0)
450 * ---this is blank---------------- DlcDirBlankTop
451 * Directory (query server 2) DlcDirAccess (adrbk_num 1)
452 * Subtitle DlcDirSubTitle (adrbk_num 1)
453 * (not a visible line) DlcEnd
454 * (not a visible line) DlcEnd
457 * There is a combined-style display triggered by the F_CMBND_ABOOK_DISP
458 * feature. It's a mixture of the top-level and open addrbook displays. When an
459 * addrbook is opened the rest of the addrbooks don't disappear from the
460 * screen. In this view, the ClickHere lines can be replaced with the entire
461 * contents of the addrbook, but the other stuff remains on the screen, too.
462 * Here are the types of lines and where they fall in the
463 * combined-style display:
465 * (not a visible line) DlcBeginning
466 * (not a visible line) DlcBeginning
467 * (not a visible line) DlcTwoBeforeBeginning
468 * (not a visible line) DlcOneBeforeBeginning
469 * -------------------------------- DlcTitleDashTopOld
470 * Title DlcTitleOld
471 * -------------------------------- DlcTitleDashBottomOld
472 * ---this is blank---------------- DlcTitleBlankBottom
473 * ClickHere DlcClickHereOld
474 * ---this is blank---------------- DlcTitleBlankTop
475 * -------------------------------- DlcTitleDashTopOld
476 * Title DlcTitleOld
477 * -------------------------------- DlcTitleDashBottomOld
478 * ---this is blank---------------- DlcTitleBlankBottom
479 * ClickHere DlcClickHereOld
480 * ---this is blank---------------- DlcDirDelim1
481 * -------------------------------- DlcDirDelim1a
482 * Directories DlcDirDelim1b
483 * -------------------------------- DlcDirDelim1c
484 * ---this is blank---------------- DlcDirDelim2
485 * Directory (query server 1) DlcDirAccess (adrbk_num 0)
486 * Subtitle DlcDirSubTitle (adrbk_num 0)
487 * ---this is blank---------------- DlcDirBlankTop
488 * Directory (query server 2) DlcDirAccess (adrbk_num 1)
489 * Subtitle DlcDirSubTitle (adrbk_num 1)
490 * (not a visible line) DlcEnd
491 * (not a visible line) DlcEnd
493 * If there are no addrbooks in either of the two sections, or no Directory
494 * servers, then that section is left out of the display. If there is only
495 * one address book and no Directories, then the user goes directly into the
496 * single addressbook view which looks like:
498 * if(no entries in addrbook)
500 * (not a visible line) DlcBeginning
501 * (not a visible line) DlcBeginning
502 * (not a visible line) DlcTwoBeforeBeginning
503 * (not a visible line) DlcOneBeforeBeginning
504 * Empty or NoPerm or NoAbooks DlcEmpty, DlcZoomEmpty, DlcNoPermission,
505 * or DlcNoAbooks
506 * (not a visible line) DlcEnd
507 * (not a visible line) DlcEnd
509 * else
511 * (not a visible line) DlcBeginning
512 * (not a visible line) DlcBeginning
513 * (not a visible line) DlcTwoBeforeBeginning
514 * (not a visible line) DlcOneBeforeBeginning
515 * Simple Entry DlcSimple
516 * Simple Entry DlcSimple
517 * Simple Entry DlcSimple
518 * DlcListBlankTop
519 * List Header DlcListHead
520 * Unexpanded List DlcListClickHere
521 * or
522 * Empty List DlcListEmpty
523 * or
524 * List Entry 1 DlcListEnt
525 * List Entry 2 DlcListEnt
526 * DlcListBlankBottom
527 * List Header DlcListHead
528 * List Entry 1 DlcListEnt
529 * List Entry 2 DlcListEnt
530 * List Entry 3 DlcListEnt
531 * DlcListBlankBottom
532 * Simple Entry DlcSimple
533 * DlcListBlankTop
534 * List Header DlcListHead
535 * Unexpanded List DlcListClickHere
536 * (not a visible line) DlcEnd
537 * (not a visible line) DlcEnd
539 * The config screen view is similar to the top-level view except there
540 * is no directory section (it has it's own config screen) and if there
541 * are zero personal addrbooks or zero global addrbooks then a placeholder
542 * line of type DlcPersAdd or DlcGlobAdd takes the place of the DlcTitle
543 * line.
545 typedef struct dl_cache {
546 long global_row; /* disp_list row number */
547 adrbk_cntr_t dlcelnum; /* which elnum from that addrbook */
548 adrbk_cntr_t dlcoffset; /* offset in a list, only for ListEnt rows */
549 short adrbk_num; /* which address book we're related to */
550 DlCacheType type; /* type of this row */
551 AddrScrn_Disp dl; /* the actual dl that goes with this row */
552 } DL_CACHE_S;
555 typedef enum {Nickname, Fullname, Addr, Filecopy, Comment, Notused,
556 Def, WhenNoAddrDisplayed, Checkbox, Selected} ColumnType;
559 * Users can customize the addrbook display, so this tells us which data
560 * is in a particular column and how wide the column is. There is an
561 * array of these per addrbook, of length NFIELDS (number of possible cols).
563 typedef struct column_description {
564 ColumnType type;
565 WidthType wtype;
566 int req_width; /* requested width (for fixed and percent types) */
567 int width; /* actual width to use */
568 int old_width;
569 } COL_S;
572 /* address book attributes for peraddrbook type */
573 #define GLOBAL 0x1 /* else it is personal */
574 #define REMOTE_VIA_IMAP 0x2 /* else it is a local file */
577 typedef enum {TotallyClosed, /* hash tables not even set up yet */
578 Closed, /* data not read in, no display list */
579 NoDisplay, /* data is accessible, no display list */
580 HalfOpen, /* data not accessible, initial display list is set */
581 ThreeQuartOpen, /* like HalfOpen without partial_close */
582 Open /* data is accessible and display list is set */
583 } OpenStatus;
586 * There is one of these per addressbook.
588 typedef struct peraddrbook {
589 unsigned type;
590 AccessType access;
591 OpenStatus ostatus;
592 char *abnick, /* kept internally in UTF-8 */
593 *filename;
594 AdrBk *address_book; /* the address book handle */
595 int gave_parse_warnings;
596 COL_S disp_form[NFIELDS]; /* display format */
597 int nick_is_displayed; /* these are for convenient, */
598 int full_is_displayed; /* fast access. Could get */
599 int addr_is_displayed; /* same info from disp_form. */
600 int fcc_is_displayed;
601 int comment_is_displayed;
602 STORE_S *so; /* storage obj for addrbook
603 temporarily stored here */
604 } PerAddrBook;
608 * This keeps track of the state of the screen and information about all
609 * the address books. We usually only have one of these but sometimes
610 * we save a version of this state (with save_state) and re-call the
611 * address book functions. Then when we pop back up to where we were
612 * (with restore_state) the screen and the state of the address books
613 * is restored to what it was.
615 typedef struct addrscreenstate {
616 PerAddrBook *adrbks; /* array of addrbooks */
617 int initialized, /* have we done at least simple init? */
618 n_addrbk, /* how many addrbooks are there */
619 how_many_personals, /* how many of those are personal? */
620 cur, /* current addrbook */
621 cur_row, /* currently selected line */
622 old_cur_row, /* previously selected line */
623 l_p_page; /* lines per (screen) page */
624 long top_ent; /* index in disp_list of top entry on screen */
625 int ro_warning, /* whether or not to give warning */
626 checkboxes, /* whether or not to display checkboxes */
627 selections, /* whether or not to display selections */
628 do_bold, /* display selections in bold */
629 no_op_possbl, /* user can't do anything with current conf */
630 zoomed, /* zoomed into view only selected entries */
631 config, /* called from config screen */
632 n_serv, /* how many directory servers are there */
633 n_impl; /* how many of those have impl bit set */
634 #ifdef _WINDOWS
635 long last_ent; /* index of last known entry */
636 #endif
637 } AddrScrState;
641 * AddrBookScreen and AddrBookConfig are the maintenance screens, all the
642 * others are selection screens. The AddrBookConfig screen is an entry
643 * point from the Setup/Addressbooks command in the main menu. Those that
644 * end in Com are called from the pico HeaderEditor, either while in the
645 * composer or while editing an address book entry. SelectManyNicks
646 * returns a comma-separated list of nicknames. SelectAddrLccCom and
647 * SelectNicksCom return a comma-separated list of nicknames.
648 * SelectNickTake, SelectNickCom, and SelectNick all return a single
649 * nickname. The ones that returns multiple nicknames or multiple
650 * addresses all allow ListMode. They are SelectAddrLccCom,
651 * SelectNicksCom, and SelectMultNoFull.
653 typedef enum {AddrBookScreen, /* maintenance screen */
654 AddrBookConfig, /* config screen */
655 SelectAddrLccCom, /* returns list of nicknames of lists */
656 SelectNicksCom, /* just like SelectAddrLccCom, but allows
657 selecting simple *and* list entries */
658 SelectNick, /* returns single nickname */
659 SelectNickTake, /* Same as SelectNick but different help */
660 SelectNickCom, /* Same as SelectNick but from composer */
661 SelectManyNicks, /* Returns list of nicks */
662 SelectAddr, /* Returns single address */
663 SelectAddrNoFull, /* Returns single address without fullname */
664 SelectMultNoFull /* Returns mult addresses without fullname */
665 } AddrBookArg;
668 typedef struct save_state_struct {
669 AddrScrState *savep;
670 OpenStatus *stp;
671 DL_CACHE_S *dlc_to_warp_to;
672 } SAVE_STATE_S;
675 typedef struct act_list {
676 PerAddrBook *pab;
677 adrbk_cntr_t num,
678 num_in_dst;
679 unsigned int skip:1,
680 dup:1;
681 } ACTION_LIST_S;
684 typedef struct ta_abook_state {
685 PerAddrBook *pab;
686 SAVE_STATE_S state;
687 } TA_STATE_S;
691 * Many of these should really only have a single value but we give them
692 * an array for uniformity.
694 typedef struct _vcard_info {
695 char **nickname;
696 char **fullname;
697 char *first;
698 char *middle;
699 char *last;
700 char **fcc;
701 char **note;
702 char **title;
703 char **tel;
704 char **email;
705 } VCARD_INFO_S;
708 extern AddrScrState as;
709 extern jmp_buf addrbook_changed_unexpectedly;
710 extern long msgno_for_pico_callback;
711 extern BODY *body_for_pico_callback;
712 extern ENVELOPE *env_for_pico_callback;
713 extern int ab_nesting_level;
717 * These constants are supposed to be suitable for use as longs where the longs
718 * are representing a line number or message number.
719 * These constants aren't suitable for use with type adrbk_cntr_t. There is
720 * a constant called NO_NEXT which you probably want for that.
722 #define NO_LINE (2147483645L)
723 #define CHANGED_CURRENT (NO_LINE + 1L)
727 * The do-while stuff is so these are statements and can be written with
728 * a following ; like a regular statement without worrying about braces and all.
730 #define SKIP_SPACE(p) do{while(*p && *p == SPACE)p++;}while(0)
731 #define SKIP_TO_TAB(p) do{while(*p && *p != TAB)p++;}while(0)
732 #define RM_END_SPACE(start,end) \
733 do{char *_ptr = end; \
734 while(--_ptr >= start && *_ptr == SPACE)*_ptr = '\0';}while(0)
735 #define REPLACE_NEWLINES_WITH_SPACE(p) \
736 do{register char *_qq; \
737 for(_qq = p; *_qq; _qq++) \
738 if(*_qq == '\n' || *_qq == '\r') \
739 *_qq = SPACE;}while(0)
740 #define DELETED "#DELETED-"
741 #define DELETED_LEN 9
744 #define ONE_HUNDRED_DAYS (60L * 60L * 24L * 100L)
747 * When address book entries are deleted, they are left in the file
748 * with the nickname prepended with a string like #DELETED-96/01/25#,
749 * which stands for year 96, month 1, day 25 of the month. When one of
750 * these entries is more than ABOOK_DELETED_EXPIRE_TIME seconds old,
751 * then it will be totally removed from the address book the next time
752 * an adrbk_write() is done. This is for emergencies where somebody
753 * deletes something from their address book and would like to get it
754 * back. You get it back by editing the nickname field manually to remove
755 * the extra 18 characters off the front.
757 #ifndef ABOOK_DELETED_EXPIRE_TIME
758 #define ABOOK_DELETED_EXPIRE_TIME ONE_HUNDRED_DAYS
759 #endif
762 #ifdef ENABLE_LDAP
763 typedef struct _cust_filt {
764 char *filt;
765 int combine;
766 } CUSTOM_FILT_S;
768 #define RUN_LDAP "LDAP: "
769 #define LEN_RL 6
770 #define QRUN_LDAP "\"LDAP: "
771 #define LEN_QRL 7
772 #define LDAP_DISP "[ LDAP Lookup ]"
773 #endif
777 * There are no restrictions on the length of any of the fields, except that
778 * there are some restrictions in the current input routines.
782 * The on-disk address book has entries that look like:
784 * Nickname TAB Fullname TAB Address_Field TAB Fcc TAB Comment
786 * An entry may be broken over more than one line but only at certain
787 * spots. A continuation line starts with spaces (spaces, not white space).
788 * One place a line break can occur is after any of the TABs. The other
789 * place is in the middle of a list of addresses, between addresses.
790 * The Address_Field may be either a simple address without the fullname
791 * or brackets, or it may be an address list. An address list is
792 * distinguished by the fact that it begins with "(" and ends with ")".
793 * Addresses within a list are comma separated and each address in the list
794 * may be a full rfc822 address, including Fullname and so on.
796 * Examples:
797 * fred TAB Flintstone, Fred TAB fred@bedrock.net TAB fcc-flintstone TAB comment
798 * or
799 * fred TAB Flintstone, Fred TAB \n
800 * fred@bedrock.net TAB fcc-flintstone TAB \n
801 * comment
802 * somelist TAB Some List TAB (fred, \n
803 * Barney Rubble <barney@bedrock.net>, wilma@bedrock.net) TAB \n
804 * fcc-for-some-list TAB comment
808 /* exported prototypes */
809 AdrBk *adrbk_open(PerAddrBook *, char *, char *, size_t, int);
810 int adrbk_is_in_sort_order(AdrBk *, int);
811 adrbk_cntr_t adrbk_count(AdrBk *);
812 AdrBk_Entry *adrbk_get_ae(AdrBk *, a_c_arg_t);
813 AdrBk_Entry *adrbk_lookup_by_nick(AdrBk *, char *, adrbk_cntr_t *);
814 AdrBk_Entry *adrbk_lookup_by_addr(AdrBk *, char *, adrbk_cntr_t *);
815 char *adrbk_formatname(char *, char **, char **);
816 void adrbk_clearrefs(AdrBk *);
817 AdrBk_Entry *adrbk_newentry(void);
818 AdrBk_Entry *copy_ae(AdrBk_Entry *);
819 int adrbk_add(AdrBk *, a_c_arg_t, char *, char *, char *, char *,
820 char *, Tag, adrbk_cntr_t *, int *, int, int, int);
821 int adrbk_append(AdrBk *, char *, char *, char *,
822 char *, char *, Tag, adrbk_cntr_t *);
823 int adrbk_delete(AdrBk *, a_c_arg_t, int, int, int, int);
824 int adrbk_listdel(AdrBk *, a_c_arg_t, char *);
825 int adrbk_listdel_all(AdrBk *, a_c_arg_t);
826 int adrbk_nlistadd(AdrBk *, a_c_arg_t,adrbk_cntr_t *,int *,char **,int,int,int);
827 void adrbk_check_validity(AdrBk *, long);
828 MAILSTREAM *adrbk_handy_stream(char *);
829 void adrbk_close(AdrBk *);
830 void adrbk_partial_close(AdrBk *);
831 void note_closed_adrbk_stream(MAILSTREAM *);
832 int adrbk_write(AdrBk *, a_c_arg_t, adrbk_cntr_t *, int *, int, int);
833 void free_ae(AdrBk_Entry **);
834 void exp_free(EXPANDED_S *);
835 int exp_is_expanded(EXPANDED_S *, a_c_arg_t);
836 int exp_howmany_expanded(EXPANDED_S *);
837 int exp_any_expanded(EXPANDED_S *);
838 adrbk_cntr_t exp_get_next(EXPANDED_S **);
839 void exp_set_expanded(EXPANDED_S *, a_c_arg_t);
840 void exp_unset_expanded(EXPANDED_S *, a_c_arg_t);
841 int adrbk_sort(AdrBk *, a_c_arg_t, adrbk_cntr_t *, int);
842 int any_ab_open(void);
843 void init_ab_if_needed(void);
844 int init_addrbooks(OpenStatus, int, int, int);
845 void addrbook_reset(void);
846 void addrbook_redo_sorts(void);
847 AccessType adrbk_access(PerAddrBook *);
848 void trim_remote_adrbks(void);
849 void completely_done_with_adrbks(void);
850 void init_abook(PerAddrBook *, OpenStatus);
851 int adrbk_check_all_validity_now(void);
852 int adrbk_check_and_fix(PerAddrBook *, int, int, int);
853 int adrbk_check_and_fix_all(int, int, int);
854 void adrbk_maintenance(void);
855 char **parse_addrlist(char *);
856 char *skip_to_next_addr(char *);
857 void add_forced_entries(AdrBk *);
858 int any_addressbook_in_remote_stream(MAILSTREAM *);
860 #endif /* PITH_ADRBKLIB_INCLUDED */