1
;; bbdb-gnokii.el --- Export phone entries from BBDB to gnokii contacts file.
4
;; Copyright (C) 2000, 2003, 2004, 2005, 2006
5
;; Martin Schwenke, Reiner Steib, Len Trigg
6
;; Authors: Martin Schwenke <martin@meltin.net>,
7
;; Reiner Steib <Reiner.Steib@gmx.de>,
8
;; Len Trigg <len@reeltwo.com>
9
;; Maintainer: Martin Schwenke <martin@meltin.net>
10
;; Created: 23 August 2000
11
;; $Id: bbdb-gnokii.el,v 1.16 2006/04/19 13:02:09 martins Exp $
12
;; Keywords: BBDB, Nokia, gnokii
13
;; X-URL: http://meltin.net/hacks/emacs/
15
;; This program is free software; you can redistribute it and/or modify
16
;; it under the terms of the GNU General Public License as published by
17
;; the Free Software Foundation; either version 2, or (at your option)
20
;; This program is distributed in the hope that it will be useful,
21
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
;; GNU General Public License for more details.
25
;; If you have not received a copy of the GNU General Public License
26
;; along with this software, it can be obtained from the GNU Project's
27
;; World Wide Web server (http://www.gnu.org/copyleft/gpl.html), from
28
;; its FTP server (ftp://ftp.gnu.org/pub/gnu/GPL), by sending an electronic
29
;; mail to this program's maintainer or by writing to the Free Software
30
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35
;; Exports BBDB phone entries to a contacts file that can be used by
36
;; gnokii to write them to a Nokia mobile phone.
38
;; No responsibility for blowing up your phone... blah, blah, blah...
39
;; I recommend dumping your phone book to a file (using xgnokii, say)
40
;; and keeping it in a safe place until you are sure that
41
;; bbdb-gnokii.el doesn't do anything stupid.
43
;; The latest version of this file is available via:
45
;; http://meltin.net/hacks/emacs/
47
;; The gnokii web site is
49
;; http://www.gnokii.org/
51
;; bbdb-gnokii.el is loosely based on JWZ's bbdb-pilot-jwz.el.
53
;; gnokii expects a file with the following format:
55
;; name;number;memory_type;entry_location;caller_group_number;\
56
;; subentry_type;subentry_number_type;subentry_id;subentry_text
58
;; The length and syntax of "name" and "number" are limited, so some
59
;; munging goes on. You can adjust the munging to your needs by
60
;; customizing the variables `bbdb-gnokii-firstname-transform',
61
;; `bbdb-gnokii-lastname-transform' and
62
;; `bbdb-gnokii-location-transform'.
64
;; The default settings of these variables reflect Martin's preferences.
65
;; Here is a combination of alternative settings used by Reiner:
68
;; ;; Use long firstnames and lastnames and a short location:
69
;; bbdb-gnokii-firstname-transform 'bbdb-gnokii-transform-word
70
;; bbdb-gnokii-lastname-transform 12
71
;; bbdb-gnokii-location-transform 'bbdb-gnokii-transform-location
72
;; bbdb-gnokii-max-name-length 16)
74
;; The memory_type specifies where to write the contacts (phone memory
75
;; or SIM card). See variable `bbdb-gnokii-default-memory-type' and
76
;; it's documentation for details.
80
;; Add this to your ~/.emacs or equivalent:
83
;; 'bbdb-gnokii-export
85
;; "Export phone entries from BBDB to a Gnokii contacts file."
88
;; If you want to add some standard entries to your phone, you can put
89
;; them in a file and set the following variable:
91
;; (setq bbdb-gnokii-extras-file
92
;; (expand-file-name "~/.bbdb-gnokii-extras.txt"))
94
;; The contents of the specified file get appended to the file
95
;; generated from the BBDB (cf. `bbdb-gnokii-extras-file-position').
96
;; My phone vendor preloads a bunch of their numbers into the SIM
97
;; card, and I'm keeping them until I'm sure they're not useful!
99
;; Entries are only extracted from the BBDB for entries that have a
100
;; gnokii field. In general, if this field is present, then all of
101
;; the phone numbers (except those that have locations listed in
102
;; `bbdb-gnokii-exclude-locations') will be exported.
106
;; Fred Smith - Widget, Inc.
107
;; mobile: (04) 1234 5678
108
;; home: (02) 1234 5678
111
;; will have 2 items exported:
113
;; Fred S mobile;0412345678;...
114
;; Fred S home;0212345678;...
116
;; For entries with a name, the default generated name is the first
117
;; word of firstname, space, first letter of lastname.
119
;; For entries without a name, but with a company, the default
120
;; generated name is the first word of the company name.
122
;; The phone number locations are only appended if there is more than
123
;; 1 phone entry exported.
125
;; If the gnokii field contains a string in double-quotes, then it
126
;; will be used as the name.
128
;; If the gnokii field contains something like location=X then the
129
;; number for location will be put into speed-dial location X. All
130
;; other entries are put between `bbdb-gnokii-general-min-location'
131
;; and `bbdb-gnokii-general-max-location'.
133
;; If the gnokii field contains something like (Y) then the entry will
134
;; belong to caller group Y, otherwise
135
;; `bbdb-gnokii-default-caller-group' is used.
139
;; Fred Smith - Widget, Inc.
140
;; mobile: (04) 1234 5678
141
;; home: (02) 1234 5678
142
;; fax: (02) 8765 4321
143
;; gnokii: "Freddy" (0) mobile=2 home=3
145
;; will have 2 items exported:
147
;; Freddy mobile;0412345678;...;0;
148
;; Freddy home;0212345678;...;0;
150
;; No item is exported for the fax number because it is a member of
151
;; `bbdb-gnokii-exclude-locations'.
153
;; If the gnokii field contains "skip=foo", the phone number corresponding to
154
;; the location "foo" will not be exported.
156
;; You can also export a whole BBDB record to a single gnokii entry by
157
;; setting `bbdb-gnokii-phonebook-style' to `multi' or `mega'. In
158
;; this style the default phone number can be set by specifying the
159
;; associated location in the BBDB gnokii field. For example, if the
160
;; gnokii field contains "[work]" then the phone number with location
161
;; "work" will be the default one. If no default location is
162
;; specified in the gnokii field, then the order of preference is
163
;; determined by `bbdb-gnokii-preferred-phone-locations'. If
164
;; `bbdb-gnokii-phonebook-style' is set to `mega', an email address
165
;; and postal address are also added to the gnokii entry, when
168
;; See the variables and code below for more details. You may check all
169
;; customizable variables using `M-x customize-group RET bbdb-gnokii RET'.
175
;; $Log: bbdb-gnokii.el,v $
176
;; Revision 1.16 2006/04/19 13:02:09 martins
177
;; Function bbdb-gnokii-do-name now just uses firstname if lastname is
178
;; not set. Suggested by Magnus Henoch <mange@freemail.hu>.
180
;; Revision 1.15 2005/06/06 09:52:49 martins
181
;; Added support for gnokii entries with multiple phone numbers using
182
;; subentries, implemented using a variation and subset of code by Len
183
;; Trigg: new variables bbdb-gnokii-phonebook-style and
184
;; bbdb-gnokii-preferred-phone-locations; removed variable
185
;; bbdb-gnokii-insert-extra-fields (replaced by
186
;; bbdb-gnokii-phonebook-style); removed defstruct bbdb-gnokii; replaced
187
;; functions bbdb-gnokii-convert and bbdb-gnokii-format with new function
188
;; bbdb-gnokii-format-record, which has most of the implementation
189
;; details for this feature; new functions bbdb-gnokii-format-address,
190
;; bbdb-gnokii-phones-find-location, bbdb-gnokii-get-default-phone;
191
;; retain '+' in phone number in function bbdb-gnokii-fix-phone;
192
;; bbdb-gnokii-export just calls bbdb-gnokii-format-record for each
193
;; record, instead of converting and then formatting; added Len Trigg to
194
;; to copyright and authors.
196
;; Revision 1.14 2004/03/30 12:01:29 martins
197
;; After discussion with Reiner, changed the names of the following
200
;; bbdb-gnokii-default-group -> bbdb-gnokii-default-caller-group
201
;; bbdb-gnokii-default-memtype -> bbdb-gnokii-default-memory-type
202
;; bbdb-gnokii-general-maxpos -> bbdb-gnokii-general-max-location
203
;; bbdb-gnokii-general-minpos -> bbdb-gnokii-general-min-location
204
;; bbdb-gnokii-speed-maxpos -> bbdb-gnokii-speed-dial-max-location
205
;; bbdb-gnokii-speed-minpos -> bbdb-gnokii-speed-dial-min-location
207
;; for consistency with gnokii documentation, and changed associated
208
;; documentation accordingly. In struct bbdb-gnokii- changed name of
209
;; member `mempos' to `location'. Also changed function names:
211
;; bbdb-gnokii-do-mempos -> bbdb-gnokii-do-location
212
;; bbdb-gnokii-do-group -> bbdb-gnokii-do-caller-group
214
;; Revision 1.13 2004/03/02 00:50:53 martins
215
;; Documentation cleanups by Reiner Steib <Reiner.Steib@gmx.de>.
217
;; Revision 1.12 2004/02/27 03:40:59 martins
218
;; bbdb-gnokii-default-memtype now has default value of "SM" (for
219
;; compatibility with xgnokii >= 0.6) - documentation and customisation
220
;; choices have also been improved. bbdb-gnokii-default-group's
221
;; documentation and customisation choices have also been improved.
222
;; Changes implemented by Reiner Steib <Reiner.Steib@gmx.de>.
224
;; Revision 1.11 2004/02/25 01:16:08 martins
225
;; Added RCS Log section in History and imported previous entries.
226
;; Thanks again to Reiner.
228
;; Revision 1.10 2004/02/07 11:47:04 martins
229
;; Replaced uses of bbdb-gnokii-extra-tag with bbdb-gnokii-extra-tags.
232
;; Revision 1.9 2004/02/07 11:40:31 martins
233
;; `bbdb-gnokii-extra-tags': New variable for Siemens C35 used in
234
;; `bbdb-gnokii-export'. Exchanged defun and defalias:
235
;; bbdb-gnokii-export vs. bbdb-to-gnokii-file. Changed documentation
236
;; section to mention bbdb-gnokii-export, not bbdb-to-gnokii. Renamed
237
;; function bbdb-record-to-gnokii-records to bbdb-gnokii-convert. Minor
238
;; cosmetic fixes. Thanks to Reiner Steib <Reiner.Steib@gmx.de>.
240
;; Revision 1.8 2004/02/06 03:07:33 martins
241
;; Merged changes from Reiner Steib <reiner.steib@gmx.de>: Made
242
;; variables customizable. Did some checkdoc fixes. Made many things
243
;; more flexible, especially the shortening of firstname, lastname and
244
;; location strings. Added `bbdb-gnokii-add-field'. Also replaced
245
;; variable `bbdb-gnokii-maxpos' with `bbdb-gnokii-general-minpos' and
246
;; `bbdb-gnokii-general-maxpos'. Added information about where to get
247
;; latest version. Various documentation fixes. Added variable
248
;; `bbdb-gnokii-insert-extra-fields'. Various documentation fixes.
249
;; Removed declarations of variables `bbdb-gnokii-mempos' and
250
;; `bbdb-gnokii-speed-done' (since they are bound in a `let').
252
;; Revision 1.7 2003/07/01 01:44:29 martins
253
;; Added extra fields to output, which seem to be required for newer
256
;; Revision 1.6 2003/06/30 01:58:10 martins
257
;; (bbdb-gnokii-do-name): Handle case where lastname is empty.
259
;; Revision 1.5 2001/02/12 00:10:45 martin
260
;; Changed e-mail address.
262
;; Revision 1.4 2000/10/04 00:41:58 martins
263
;; Changed default-memtype back to "A".
265
;; Revision 1.3 2000/08/25 02:58:15 martins
266
;; - Added documentation and stuff at top.
267
;; - Changed spelling from Gnokii to gnokii.
268
;; - Changed default memory type to work with command-line gnokii.
269
;; - Reduced allowable length of names.
270
;; - Added bbdb-gnokii-exclude-locations and associated filtering.
271
;; Thanks to Chris Yeoh.
272
;; - Added various comments.
274
;; Revision 1.2 2000/08/24 11:52:57 martins
275
;; Fixed RCS Id string.
277
;; Revision 1.1 2000/08/24 11:52:39 martins
284
;; Only for `bbdb-gnokii-add-field':
285
(autoload 'bbdb-merge-interactively "bbdb-snarf" nil nil)
286
(autoload 'bbdb-add-new-field "bbdb-com" nil nil)
288
(defgroup bbdb-gnokii nil
289
"Sync BBDB and gnokii."
292
(defcustom bbdb-gnokii-transform-word-regexp
293
(if (string-match "[[:word:]]" "x")
295
;; old Emacsen (e.g. Emacs 20) don't support character classes.
297
"Regexp used to shorten names in `bbdb-gnokii-transform-word'."
299
:type '(choice (const :tag "first word" "[^-[:word:]]")
300
(const :tag "ascii" "[^-A-Za-z]")
301
(regexp :tag "Other")))
303
(defun bbdb-gnokii-transform-max (name &optional limit)
304
"Limit NAME to LIMIT characters."
305
(if (> (length name) limit)
306
(substring name 0 limit)
309
(defun bbdb-gnokii-transform-word (name &optional regexp)
310
"Shorten NAME to first word.
311
`bbdb-gnokii-transform-word-regexp' is used unless REGEXP is given."
313
0 (string-match (or regexp bbdb-gnokii-transform-word-regexp) name)))
315
(defun bbdb-gnokii-transform-location (location)
316
"Shorten LOCATION field."
317
;; The default BBDB location "Office" and "Other" both give "O"
318
(if (string= name "Other")
320
(bbdb-gnokii-transform-max location 1)))
322
(defcustom bbdb-gnokii-firstname-transform 'bbdb-gnokii-transform-word
323
"How to transform the lastname field to short variant.
324
If a function, call it with the name as it's argument. If a number, use
325
substring with maximal length number."
327
:type '(choice (const bbdb-gnokii-transform-word)
331
(defcustom bbdb-gnokii-lastname-transform 1
332
"How to transform the lastname field to short variant.
333
If a function, call it with the name as it's argument. If a number, use
334
substring with maximal length number."
336
:type '(choice (const bbdb-gnokii-transform-word)
340
(defcustom bbdb-gnokii-location-transform 10
341
"Transform the location field to short variant.
342
If a function, call it with the name as it's argument. If a number, use
343
substring with maximal length number."
345
:type '(choice (const bbdb-gnokii-transform-location)
349
(defun bbdb-gnokii-apply-transform (transform name)
350
"Apply transformation TRANSFORM to NAME and return a shortened name."
352
((functionp transform)
353
(funcall transform name))
355
(bbdb-gnokii-transform-max name transform))
358
(defcustom bbdb-gnokii-extras-file nil
359
"Name of file containing extra entries to add to gnokii."
361
:type '(choice (const :tag "None" nil)
364
(defcustom bbdb-gnokii-extra-tags nil
365
"List of two string elements: \"\(\"tag\" \"indicator\"\)\" or nil.
366
For each occurance of the form \"location=tag\" in the BBDB gnokii field, the
367
gnokii string \"indicator\" will be appended to the generated name in the
368
gnokii file. In some Siemens phones \(C35 and possibly others\), the
369
indicator \"!\" is used to specify a \"VIP entry\"."
371
:type '(choice (const :tag "Siemens C35 style" ("vip" "!"))
372
(list (symbol :tag "BBDB tag")
373
(symbol :tag "Gnokii string"))))
375
(defcustom bbdb-gnokii-default-output-file nil
376
"Name of the default output file.
377
If the filename contains the string \"%s\", it will be replaced
378
with the current date in ISO format (YYYY-MM-DD)."
380
:type '(choice (const :tag "None" nil)
383
(defcustom bbdb-gnokii-extras-file-position 'bottom
384
"Where to insert `bbdb-gnokii-extras-file'."
386
:type '(choice (const :tag "Top" top)
387
(const :tag "Bottom" bottom)))
389
(defcustom bbdb-gnokii-inserted-hook nil
390
"Hook run after all records from BBDB were inserted into the output buffer.
391
The hook is called in the output buffer immediately before saving the buffer."
395
(defcustom bbdb-gnokii-confirm-kill nil
396
"Ask for confirmation before killing the output buffer."
400
(defcustom bbdb-gnokii-phonebook-style 'single
401
"Style for phonebook entries.
402
This affects the number of phone numbers per gnokii entry and the way
403
the name is constructed. `single' (the default) allows only a single
404
phone number per gnokii entry, and also generates a subentry for that
405
phone number. `ancient' also allows only a single phone number per
406
gnokii entry, but generates no subentry - older versions of gnokii
407
seem to work like this. `multiple' causes all phone numbers for a
408
BBDB entry to be put into a single gnokki entry, using multiple
409
subentries - in this case the location is also never appended to the
410
name. `mega' is like multiple but causes the 1st email address and
411
postal address to also be put into the gnokii entry. Note that
412
`multiple' and `mega' probably won't work well with
413
`bbdb-gnokii-default-memory-type' set to \"SM\"."
414
:type '(choice (const :tag "Single with subentry" single)
415
(const :tag "Single without subentry" ancient)
416
(const :tag "Multiple subentries" multiple)
417
(const :tag "Subentries, email, postal" mega)))
419
(defcustom bbdb-gnokii-speed-dial-min-location 1
420
"Minimum memory location allowed for speed dial entries.
421
See also `bbdb-gnokii-general-min-location',
422
`bbdb-gnokii-general-max-location' and
423
`bbdb-gnokii-speed-dial-max-location'. The range for speed dial
424
entries should not overlap with the range for general entries, or
425
entries found in `bbdb-gnokii-extras-file'."
429
(defcustom bbdb-gnokii-speed-dial-max-location 9
430
"Maximum memory location allowed for speed dial entries.
431
See also `bbdb-gnokii-general-min-location',
432
`bbdb-gnokii-general-max-location' and
433
`bbdb-gnokii-speed-dial-min-location'. The range for speed dial
434
entries should not overlap with the range for general entries, or
435
entries found in `bbdb-gnokii-extras-file'."
439
(defcustom bbdb-gnokii-general-min-location 10
440
"Minimum memory location allowed for general BBDB to gnokii entries.
441
See also `bbdb-gnokii-general-max-location',
442
`bbdb-gnokii-speed-dial-min-location' and
443
`bbdb-gnokii-speed-dial-max-location'. The range for speed dial
444
entries should not overlap with the range for general entries, or
445
entries found in `bbdb-gnokii-extras-file'."
449
(defcustom bbdb-gnokii-general-max-location 89
450
"Maximum memory location allowed for general BBDB to gnokii entries.
451
See also `bbdb-gnokii-general-min-location',
452
`bbdb-gnokii-speed-dial-min-location' and
453
`bbdb-gnokii-speed-dial-max-location'. The range for speed dial
454
entries should not overlap with the range for general entries, or
455
entries found in `bbdb-gnokii-extras-file'."
459
(defcustom bbdb-gnokii-default-memory-type "SM"
460
"Default type of phone memory to use for BBDB to gnokii entries.
461
\"SM\" is for SIM card, \"ME\" for the phone memory. In versions prior to
462
0.6, `xgnokii' used \"A\" is for SIM card and \"B\" for the phone memory.
463
Please see the documentation of gnokii and xgnokii for valid values."
465
:type '(choice (const :tag "SIM card" "SM")
466
(const :tag "phone memory" "ME")
467
(const :tag "SIM card (for old xgnokii)" "A")
468
(const :tag "phone memory (for old xgnokii)" "B")
469
;; Other valid memory types probably aren't writable.
470
(string :tag "Other")))
472
(defcustom bbdb-gnokii-default-caller-group 5
473
"Default caller group to put BBDB to gnokii entries into.
475
If the gnokii field contains something like \"\(N\)\" then the entry will
476
belong to caller group N, otherwise `bbdb-gnokii-default-caller-group'
477
is used. Possible values are 0 \(Family\), 1 \(VIP\), 2 \(Friends\),
478
3 \(Colleagues\), 4 \(Other group\), 5 \(No group\). Note that these
479
are defaults, you are able to change these manually in your phone.
480
See also \"caller_group_number\" in the documentation of gnokii."
482
:type '(choice (const :tag "0 (Family)" 0)
483
(const :tag "1 (VIP)" 1)
484
(const :tag "2 (Friends)" 2)
485
(const :tag "3 (Colleagues)" 3)
486
(const :tag "4 (Other group)" 4)
487
(const :tag "5 (No group)" 5)
488
(integer :tag "Other")))
490
(defcustom bbdb-gnokii-max-name-length 17
491
"Maximum allowable length of name field."
495
(defcustom bbdb-gnokii-exclude-locations '("fax")
496
"List of locations for phone numbers to exclude."
498
:type '(choice (const :tag "None" nil)
499
(const :tag "Fax" '("fax"))
500
(repeat (string :tag "Field"))))
502
(defcustom bbdb-gnokii-preferred-phone-locations '("mobile" "home" "work")
503
"List of locations for choosing default phone number in multi-phone entries.
504
The phone number associated with earliest location in this list is used.
505
Otherwise, the first phone number is used."
507
:type '(choice (repeat (string :tag "Field"))))
509
(defconst bbdb-gnokii-label-type-alist
516
"Alist mapping BBDB phones labels to gnokii phone number types.")
518
(defun bbdb-gnokii-format-record (record)
519
"Convert a BBDB RECORD to text in the current buffer."
521
(let ((allphones (bbdb-record-phones record))
522
(allnet (bbdb-record-net record))
523
(alladdresses (bbdb-record-addresses record))
524
(stuff (if (listp (bbdb-record-raw-notes record))
525
(cdr (assq 'gnokii (bbdb-record-raw-notes record)))))
527
name useloc phones default-phone print-escape-newlines)
529
(setq name (bbdb-gnokii-do-name (bbdb-record-lastname record)
530
(bbdb-record-firstname record)
531
(bbdb-record-company record)
534
;; Filter out unwanted phone locations and find default phone number.
536
(let ((p (car allphones)))
537
(if (not (or (member (bbdb-phone-location p)
538
bbdb-gnokii-exclude-locations)
539
(string-match (concat "\\<skip=\\("
540
(bbdb-phone-location p)
543
(add-to-list 'phones p)))
544
(setq allphones (cdr allphones)))
546
(if (memq bbdb-gnokii-phonebook-style '(multiple mega))
547
(setq default-phone (bbdb-gnokii-get-default-phone phones stuff)))
549
;; Only continue if they have a name, a gnokii field and some
551
(if (and name stuff phones)
553
;; Only add the location to name if there is >1 phone number
554
;; and we're not doing multiple-subentries.
555
(setq useloc (and (> (length phones) 1)
556
(memq bbdb-gnokii-phonebook-style
560
(let* ((location (bbdb-phone-location (car phones)))
561
(loc (bbdb-gnokii-apply-transform
562
bbdb-gnokii-location-transform
564
(num (bbdb-gnokii-fix-phone
565
(bbdb-phone-string (car phones))))
566
(default-loc (or (and default-phone
567
(bbdb-gnokii-apply-transform
568
bbdb-gnokii-location-transform
569
(bbdb-phone-location default-phone)))
571
(default-num (or (and default-phone
572
(bbdb-gnokii-fix-phone
573
(bbdb-phone-string default-phone)))
575
(name (if useloc (concat name " " loc) name)))
576
(if (> (length name) bbdb-gnokii-max-name-length)
577
;; Don't error out on long entries, truncate them instead.
581
"Name \"%s\" is too long. "
582
"Maybe you want to edit gnokii field.")
587
;; Make sure we don't strip location:
590
(bbdb-gnokii-transform-max
591
name (- bbdb-gnokii-max-name-length
595
(bbdb-gnokii-transform-max
596
name bbdb-gnokii-max-name-length))))))
597
;; Checking for bbdb-gnokii-extra-tags:
598
(when (and (car bbdb-gnokii-extra-tags)
599
(cadr bbdb-gnokii-extra-tags)
605
(regexp-quote (car bbdb-gnokii-extra-tags))
608
;; extra entry found, changing label:
610
(concat (bbdb-gnokii-transform-max
611
name (- bbdb-gnokii-max-name-length 1))
612
(cadr bbdb-gnokii-extra-tags))))
614
(if (= subentry-id 0)
615
(insert (format "%s;%s;%s;%s;%s"
618
bbdb-gnokii-default-memory-type
619
(bbdb-gnokii-do-location stuff default-loc)
620
(bbdb-gnokii-do-caller-group stuff))))
621
(if (not (eq bbdb-gnokii-phonebook-style 'ancient))
622
(insert (format ";11;%d;%d;%s"
623
(assoc-default location
624
bbdb-gnokii-label-type-alist
629
;; Continute along list of phone numbers.
630
(setq phones (cdr phones))
631
;; If doing multiple per entry, increment subentry-id count.
632
(if (memq bbdb-gnokii-phonebook-style '(multiple mega))
633
(setq subentry-id (1+ subentry-id))
636
(when (eq bbdb-gnokii-phonebook-style 'mega)
637
;; First email address?
639
(insert (format ";8;0;%d;%s" subentry-id (car allnet)))
640
(setq subentry-id (1+ subentry-id)))
641
;; First postal address?
643
(insert (format ";9;0;%d;%s" subentry-id
644
(bbdb-gnokii-format-address (car alladdresses))))
645
(setq subentry-id (1+ subentry-id))))
646
(if (memq bbdb-gnokii-phonebook-style '(multiple mega))
650
(defun bbdb-gnokii-format-address (address)
651
"Generates a single-line representation of an address."
653
(cond ((>= bbdb-file-format 6)
654
(setq st (bbdb-join (bbdb-address-streets address) "\\n")))
656
(setq st (bbdb-address-street1 address))
657
(if (> (length (bbdb-address-street2 address)) 0)
658
(setq st (concat st "\\n" (bbdb-address-street2 address))))
659
(if (> (length (bbdb-address-street3 address)) 0)
660
(setq st (concat st "\\n" (bbdb-address-street3 address))))))
661
(setq field (bbdb-address-city address))
662
(if (> (length field) 0) (setq st (concat st "\\n" field)))
663
(setq field (bbdb-address-state address))
664
(if (> (length field) 0) (setq st (concat st "\\n" field)))
665
(setq field (bbdb-address-zip-string address))
666
(if (> (length field) 0) (setq st (concat st "\\n" field)))
667
(setq field (bbdb-address-country address))
668
(if (> (length field) 0) (setq st (concat st "\\n" field)))
671
(defun bbdb-gnokii-do-name (lastname firstname company stuff)
672
"Construct a name from the given arguments."
679
(string-match "\"\\([^\"]+\\)\"" stuff))
680
(setq name (substring stuff (match-beginning 1) (match-end 1))))
683
;; Yay, they have a name! Default is first word of firstname,
684
;; space, first letter of lastname.
686
(bbdb-gnokii-apply-transform
687
bbdb-gnokii-firstname-transform firstname))
688
(when (> (length lastname) 0)
693
(bbdb-gnokii-apply-transform
694
bbdb-gnokii-lastname-transform lastname))))))
696
;; Yay, first word of company name!
697
;; Maybe this should be made customizable, too (Reiner Steib).
698
(setq name (substring company 0 (string-match " " company)))))
702
(defun bbdb-gnokii-do-location (stuff loc)
703
"Calculate the `location' field for a gnokii record.
704
The field content STUFF and the location LOC are used."
708
(string-match (concat "\\<" loc "=\\([0-9]+\\)") stuff))
710
(setq num (string-to-number
711
(substring stuff (match-beginning 1) (match-end 1))))
712
(if (or (< num bbdb-gnokii-speed-dial-min-location)
713
(> num bbdb-gnokii-speed-dial-max-location)
714
(member num bbdb-gnokii-speed-done))
716
"Speed dial location %d out of range or duplicate for %s"
718
(add-to-list 'bbdb-gnokii-speed-done num)))
719
(if (> bbdb-gnokii-location bbdb-gnokii-general-max-location)
720
(error "Too many records to fit in SIM card!"))
721
(setq num bbdb-gnokii-location)
722
(setq bbdb-gnokii-location (+ bbdb-gnokii-location 1)))
725
(defun bbdb-gnokii-do-caller-group (bbdb-field)
726
"Calculate the caller `group' field for given BBDB-FIELD."
730
(string-match "(\\([0-9]+\\))" bbdb-field))
731
(setq group (string-to-number
732
(substring bbdb-field (match-beginning 1) (match-end 1))))
733
(setq group bbdb-gnokii-default-caller-group))
736
(defun bbdb-gnokii-phones-find-location (location phones)
737
"Return the phone element in PHONES with given LOCATION, nil if not found."
740
(while (and (not ret) ps)
741
(if (string= location (bbdb-phone-location (car ps)))
746
(defun bbdb-gnokii-get-default-phone (phones stuff)
747
"Get the default phone entry for a record."
749
(let* ((loc (and stuff
750
(string-match "\\[\\([^]]+\\)\\]" stuff)
751
(substring stuff (match-beginning 1) (match-end 1))))
752
(locs bbdb-gnokii-preferred-phone-locations)
756
(setq ret (bbdb-gnokii-phones-find-location loc phones)))
758
(while (and (not ret) locs)
759
(setq ret (bbdb-gnokii-phones-find-location (car locs) phones))
760
(setq locs (cdr locs)))
761
(or ret (car phones))))
763
(defun bbdb-gnokii-fix-phone (phone)
764
"Change phone number PHONE to gnokii compatible form."
768
(while (> (length chars) 0)
769
(let ((h (substring chars 0 1)))
770
(if (string-match "[+0-9]" h)
771
(setq out (concat out h)))
772
(setq chars (substring chars 1))))
776
(defalias 'bbdb-to-gnokii-file 'bbdb-gnokii-export)
779
(defun bbdb-gnokii-export (filename &optional records)
780
"Export phone entries from BBDB to a gnokii contacts file FILENAME.
781
Unless RECORDS is given, all BBDB entries are processed."
783
(list (let ((default (if (stringp bbdb-gnokii-default-output-file)
784
(format bbdb-gnokii-default-output-file
785
(format-time-string "%Y-%m-%d" (current-time)))
787
(read-file-name "Output file: "
788
(file-name-directory default)
791
(file-name-nondirectory default)))))
792
(or records (setq records (bbdb-records)))
794
(set-buffer (find-file-noselect filename))
796
(let ((len (length records))
798
(bbdb-gnokii-location bbdb-gnokii-general-min-location)
799
bbdb-gnokii-speed-done)
801
(message "%d%%..." (/ (* 100 i) len))
802
(bbdb-gnokii-format-record (car records))
803
(setq records (cdr records)
805
(when (and bbdb-gnokii-extras-file
806
(file-readable-p bbdb-gnokii-extras-file))
807
(cond ((eq bbdb-gnokii-extras-file-position 'top)
808
(goto-char (point-min)))
809
((eq bbdb-gnokii-extras-file-position 'bottom)
810
(goto-char (point-max))))
811
(insert-file-contents bbdb-gnokii-extras-file))
812
(run-hooks 'bbdb-gnokii-inserted-hook)
814
;; Useful especially when testing.
815
(when (or (not bbdb-gnokii-confirm-kill)
816
(y-or-n-p "Kill output buffer? "))
817
(kill-buffer (current-buffer))))
821
(defun bbdb-gnokii-add-field (&optional records)
822
"Go through all RECORDS and ask for adding a gnokii field.
823
If RECORDS is nil, go thru all records. If a BBDB record has an
824
expire field in YYYY-MM-DD format \(e.g. \"expire=2003-12-31\"\),
825
the record is skipped if it is older than today."
827
(or records (setq records (bbdb-records)))
828
(bbdb-add-new-field 'gnokii)
829
(dolist (record records)
830
;; Go thru all records, check if we have a phone and no gnokii field.
831
(if (bbdb-record-phones record)
833
(and (listp (bbdb-record-raw-notes record))
834
(cdr (assq 'gnokii (bbdb-record-raw-notes record)))))
836
(and (listp (bbdb-record-raw-notes record))
837
(cdr (assq 'expire (bbdb-record-raw-notes record)))))
838
(name (bbdb-record-name record))
843
"%Y-%m-%d" (current-time))))))
844
(message "In record `%s': gnokii=`%s', expire=`%s', is-exp=`%s'"
845
name have-gnokii expire is-expired)
848
(message "In record `%s': is expired." name))
850
(message "In record `%s': already has gnokii field." name))
851
((y-or-n-p (format "Add gnokii field to `%s'? " name))
852
(bbdb-merge-interactively name;; name
858
(message "In record `%s': gnokii field added." name))
860
(message "In record `%s': gnokii refused interactively." name))))
861
(message "In record `%s': no phone found." (bbdb-record-name record)))))
863
(provide 'bbdb-gnokii)
865
;;; bbdb-gnokii.el ends here