1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: addrbook.c 90 2006-07-19 22:30:36Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2014 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 /*======================================================================
21 display format/support routines
24 #include "../c-client/c-client.h"
37 #include "osdep/collate.h"
40 /* internal prototypes */
41 void parse_format(char *, COL_S
*);
47 * We have to call this to set up the format of the columns. There is a
48 * separate format for each addrbook, so we need to call this for each
49 * addrbook. We call it when the pab's are built. It also depends on
50 * whether or not as.checkboxes is set, so if we go into a Select mode
51 * from the address book maintenance screen we need to re-call this. Since
52 * we can't go back out of ListMode we don't have that problem. Restore_state
53 * has to call it because of the as.checkboxes possibly being different in
57 addrbook_new_disp_form(PerAddrBook
*pab
, char **list
, int addrbook_num
,
58 int (*prefix_f
)(PerAddrBook
*, int *))
63 dprint((9, "- init_disp_form(%s) -\n",
64 (pab
&& pab
->abnick
) ? pab
->abnick
: "?"));
66 memset((void *)pab
->disp_form
, 0, NFIELDS
*sizeof(COL_S
));
67 pab
->disp_form
[1].wtype
= WeCalculate
; /* so we don't get false AllAuto */
70 as
.do_bold
= (*prefix_f
)(pab
, &column
);
72 /* if custom format is specified */
73 if(list
&& list
[0] && list
[0][0]){
74 /* find the one for addrbook_num */
76 *list
!= NULL
&& addrbook_num
;
77 addrbook_num
--,list
++)
80 /* If not enough to go around, last one repeats */
82 parse_format(last_one
, &(pab
->disp_form
[column
]));
84 parse_format(*list
, &(pab
->disp_form
[column
]));
87 /* If 2nd wtype is AllAuto, the widths are calculated old way */
88 pab
->disp_form
[1].wtype
= AllAuto
;
90 pab
->disp_form
[column
++].type
= Nickname
;
91 pab
->disp_form
[column
++].type
= Fullname
;
92 pab
->disp_form
[column
++].type
= Addr
;
94 while(column
< NFIELDS
)
95 pab
->disp_form
[column
++].type
= Notused
;
100 struct parse_tokens
{
105 struct parse_tokens ptokens
[] = {
106 {"NICKNAME", Nickname
},
107 {"FULLNAME", Fullname
},
110 {"COMMENT", Comment
},
116 * Parse format_str and fill in disp_form structure based on what's there.
118 * Args: format_str -- The format string from pinerc.
119 * disp_form -- This is where we fill in the answer.
121 * The format string consists of special tokens which give the order of
122 * the columns to be displayed. The possible tokens are NICKNAME,
123 * FULLNAME, ADDRESS, FCC, COMMENT. If a token is followed by
124 * parens with an integer inside (FULLNAME(16)) then that means we
125 * make that variable that many characters wide. If it is a percentage, we
126 * allocate that percentage of the columns to that variable. If no
127 * parens, that means we calculate it for the user. The tokens are
128 * delimited by white space. A token of DEFAULT means to calculate the
129 * whole thing as we would if no spec was given. This makes it possible
130 * to specify default for one addrbook and something special for another.
133 parse_format(char *format_str
, COL_S
*disp_form
)
137 struct parse_tokens
*pt
;
138 int nicknames
, fullnames
, addresses
, not_allauto
;
142 while(p
&& *p
&& column
< NFIELDS
){
143 p
= skip_white_space(p
); /* space for next word */
145 /* look for the ptoken this word matches */
146 for(pt
= ptokens
; pt
->name
; pt
++)
147 if(!struncmp(pt
->name
, p
, strlen(pt
->name
)))
150 /* ignore unrecognized word */
154 if((r
=strindex(p
, SPACE
)) != NULL
)
157 dprint((2, "parse_format: ignoring unrecognized word \"%s\" in address-book-formats\n", p
? p
: "?"));
158 q_status_message1(SM_ORDER
, warnings
++==0 ? 1 : 0, 4,
159 /* TRANSLATORS: an informative error message */
160 _("Ignoring unrecognized word \"%s\" in Address-Book-Formats"), p
);
165 /* skip unrecognized word */
166 while(p
&& *p
&& !isspace((unsigned char)(*p
)))
172 disp_form
[column
].type
= pt
->ctype
;
174 /* skip over name and look for parens */
175 p
+= strlen(pt
->name
);
179 while(p
&& *p
&& isdigit((unsigned char)*p
))
182 if(p
&& *p
&& *p
== ')' && p
> q
){
183 disp_form
[column
].wtype
= Fixed
;
184 disp_form
[column
].req_width
= atoi(q
);
186 else if(p
&& *p
&& *p
== '%' && p
> q
){
187 disp_form
[column
].wtype
= Percent
;
188 disp_form
[column
].req_width
= atoi(q
);
191 disp_form
[column
].wtype
= WeCalculate
;
192 if(disp_form
[column
].type
== Nickname
)
193 disp_form
[column
].req_width
= 8;
195 disp_form
[column
].req_width
= 3;
199 disp_form
[column
].wtype
= WeCalculate
;
200 if(disp_form
[column
].type
== Nickname
)
201 disp_form
[column
].req_width
= 8;
203 disp_form
[column
].req_width
= 3;
206 if(disp_form
[column
].type
== Def
){
207 /* If any type is DEFAULT, the widths are calculated old way */
211 disp_form
[column
].wtype
= AllAuto
;
212 disp_form
[column
++].type
= Nickname
;
213 disp_form
[column
].wtype
= AllAuto
;
214 disp_form
[column
++].type
= Fullname
;
215 disp_form
[column
].wtype
= AllAuto
;
216 disp_form
[column
++].type
= Addr
;
218 while(column
< NFIELDS
)
219 disp_form
[column
++].type
= Notused
;
225 /* skip text at end of word */
226 while(p
&& *p
&& !isspace((unsigned char)(*p
)))
231 q_status_message(SM_ORDER
, 0, 4,
232 _("Address-Book-Formats has no recognizable words, using default format"));
237 while(column
< NFIELDS
)
238 disp_form
[column
++].type
= Notused
;
240 /* check to see if user is just re-ordering default fields */
245 for(column
= 0; column
< NFIELDS
; column
++){
246 if(disp_form
[column
].type
!= Notused
247 && disp_form
[column
].wtype
!= WeCalculate
)
250 switch(disp_form
[column
].type
){
274 * Special case: if there is no address field specified, we put in
275 * a special field called WhenNoAddrDisplayed, which causes list
276 * entries to be displayable in all cases.
279 for(column
= 0; column
< NFIELDS
; column
++)
280 if(disp_form
[column
].type
== Notused
)
283 if(column
< NFIELDS
){
284 disp_form
[column
].type
= WhenNoAddrDisplayed
;
285 disp_form
[column
].wtype
= Special
;
289 if(nicknames
== 1 && fullnames
== 1 && addresses
== 1 && not_allauto
== 0)
290 disp_form
[0].wtype
= AllAuto
; /* set to do default widths */
295 * Find the first selectable line greater than or equal to line. That is,
296 * the first line the cursor is allowed to start on.
297 * (If there are none >= line, it will find the highest one.)
299 * Returns the line number of the found line or NO_LINE if there isn't one.
302 first_selectable_line(long int line
)
305 register PerAddrBook
*pab
;
308 /* skip past non-selectable lines */
310 !line_is_selectable(lineno
) && dlist(lineno
)->type
!= End
;
314 if(line_is_selectable(lineno
))
318 * There were no selectable lines from lineno on down. Trying looking
322 !line_is_selectable(lineno
) && dlist(lineno
)->type
!= Beginning
;
326 if(line_is_selectable(lineno
))
330 * No selectable lines at all.
331 * If some of the addrbooks are still not displayed, it is too
332 * early to set the no_op_possbl flag. Or, if some of the addrbooks
333 * are empty but writable, then we should not set it either.
335 for(i
= 0; i
< as
.n_addrbk
; i
++){
337 if(pab
->ostatus
!= Open
&&
338 pab
->ostatus
!= HalfOpen
&&
339 pab
->ostatus
!= ThreeQuartOpen
)
342 if(pab
->access
== ReadWrite
&& adrbk_count(pab
->address_book
) == 0)
352 * Returns 1 if this line is of a type that can have a cursor on it.
355 line_is_selectable(long int lineno
)
357 register AddrScrn_Disp
*dl
;
359 if((dl
= dlist(lineno
)) && (dl
->type
== Text
||
360 dl
->type
== ListEmpty
||
361 dl
->type
== TitleCmb
||
362 dl
->type
== Beginning
||