diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/app/Makefile.tpl wfdb-10.5.10/app/Makefile.tpl
--- wfdb-10.5.9/app/Makefile.tpl	2009-05-04 00:57:32.000000000 -0400
+++ wfdb-10.5.10/app/Makefile.tpl	2011-11-16 14:47:07.000000000 -0500
@@ -1,5 +1,5 @@
 # file: Makefile.tpl		G. Moody	  23 May 2000
-#				Last revised:	  26 February 2009
+#				Last revised:	  16 November 2011
 # This section of the Makefile should not need to be changed.
 
 CFILES = ann2rr.c bxb.c calsig.c ecgeval.c epicmp.c fir.c ihr.c mfilt.c \
@@ -7,13 +7,14 @@
  rdsamp.c rr2ann.c rxr.c sampfreq.c sigamp.c sigavg.c signame.c signum.c \
  skewedit.c snip.c sortann.c sqrs.c sqrs125.c sumann.c sumstats.c tach.c \
  time2sec.c wabp.c wfdb-config.c wfdbcat.c wfdbcollate.c wfdbdesc.c \
- wfdbtime.c wfdbwhich.c wqrs.c wrann.c wrsamp.c xform.c
+ wfdbmap.c wfdbsignals.c wfdbtime.c wfdbwhich.c wqrs.c wrann.c wrsamp.c xform.c
+HFILES = signal-colors.h
 XFILES = ann2rr bxb calsig ecgeval epicmp fir ihr mfilt \
  mrgann mxm nguess nst plotstm pscgen pschart psfd rdann \
  rdsamp rr2ann rxr sampfreq sigamp sigavg signame signum \
  skewedit snip sortann sqrs sqrs125 sumann sumstats tach \
  time2sec wabp wfdb-config wfdbcat wfdbcollate wfdbdesc \
- wfdbtime wfdbwhich wqrs wrann wrsamp xform
+ wfdbmap wfdbsignals wfdbtime wfdbwhich wqrs wrann wrsamp xform
 SCRIPTS = cshsetwfdb setwfdb
 PSFILES = pschart.pro psfd.pro 12lead.pro
 MFILES = Makefile
@@ -66,7 +67,7 @@
 
 # `make listing':  print a listing of WFDB applications sources
 listing:
-	$(PRINT) README $(MFILES) $(CFILES) $(PSFILES)
+	$(PRINT) README $(MFILES) $(CFILES) $(HFILES) $(PSFILES)
 
 # Rules for compiling applications that require non-standard options
 
@@ -87,5 +88,7 @@
 	$(CC) $(CFLAGS) -DPROLOG=\"$(PSPDIR)/psfd.pro\" psfd.c -o $@ $(LDFLAGS)
 sigamp:		sigamp.c
 	$(CC) $(CFLAGS) sigamp.c -o $@ $(LDFLAGS) -lm
+wfdbmap:      wfdbmap.c signal-colors.h
+	$(CC) $(CFLAGS) wfdbmap.c -o $@ $(LDFLAGS)
 wqrs:		wqrs.c
 	$(CC) $(CFLAGS) wqrs.c -o $@ $(LDFLAGS) -lm
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/app/map-record wfdb-10.5.10/app/map-record
--- wfdb-10.5.9/app/map-record	1969-12-31 19:00:00.000000000 -0500
+++ wfdb-10.5.10/app/map-record	2010-07-30 15:37:34.000000000 -0400
@@ -0,0 +1,12 @@
+#! /bin/bash
+
+# make a map of a WFDB record
+
+RL=$1
+RS=`basename $RL`
+shift
+
+wfdbmap -r $RL $* >$RS.script
+bash $RS.script >$RS.plt 2>/dev/null
+lwcat -strip -eps $RS.plt >$RS.ps
+convert -density 150 $RS.ps $RS.png
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/app/signal-colors.h wfdb-10.5.10/app/signal-colors.h
--- wfdb-10.5.9/app/signal-colors.h	1969-12-31 19:00:00.000000000 -0500
+++ wfdb-10.5.10/app/signal-colors.h	2009-04-09 16:44:18.000000000 -0400
@@ -0,0 +1,311 @@
+struct sigcolor {
+    char *color;
+    char *class;
+    char *name;
+} ctab[] = {
+"red", "ECG", "Abdomen_1",
+"red", "ECG", "Abdomen_2",
+"red", "ECG", "Abdomen_3",
+"red", "ECG", "Abdomen_4",
+"green", "Resp", "Abdomen   [ABMV]",
+"green", "Resp", "ABDO RES",
+"blue", "BP", "ABP",
+"blue", "BP", "ABP_1/2",
+"blue", "BP", "ABP_2/2",
+"blue", "BP", "ABPDias",
+"blue", "BP", "ABPMean",
+"blue", "BP", "ABPSys",
+"blue", "BP", "AOBP",
+"blue", "BP", "AOBP_1/2",
+"blue", "BP", "AOBP_2/2",
+"blue", "BP", "AOBP Dias",
+"blue", "BP", "AOBP Mean",
+"blue", "BP", "AOBP Sys",
+"blue", "BP", "NBP_1/2",
+"blue", "BP", "NBP_2/2",
+"blue", "BP", "NBP",
+"blue", "BP", "NBPDias",
+"blue", "BP", "NBPMean",
+"blue", "BP", "NBPSys",
+"blue", "BP", "ABP Dias",
+"blue", "BP", "ABP Mean",
+"blue", "BP", "ABP Sys",
+"blue", "BP", "NBP Dias",
+"blue", "BP", "NBP Mean",
+"blue", "BP", "NBP Sys",
+"blue", "BP", "ABP ",
+"red", "ECG", "A-I",
+"green", "Resp", "AIRFLOW",
+"blue", "BP", "ART",
+"blue", "BP", "ART_1/2",
+"blue", "BP", "ART Dias",
+"blue", "BP", "ART Mean",
+"blue", "BP", "ART Sys",
+"blue", "BP", "ART ",
+"blue", "BP", "ART 1",
+"blue", "BP", "ART1 ",
+"blue", "BP", "ART^M                 ",
+"red", "ECG", "A-S",
+"red", "ECG", "avf",
+"red", "ECG", "aVF",
+"red", "ECG", "AVF",
+"red", "ECG", "AVF+",
+"red", "ECG", "avl",
+"red", "ECG", "aVL",
+"red", "ECG", "AVL",
+"red", "ECG", "avr",
+"red", "ECG", "aVR",
+"red", "ECG", "AVR",
+"darkgreen", "Temp", "BLOODT",
+"darkgreen", "Temp", "BLOODT_1/3",
+"darkgreen", "Temp", "BLOODT_2/3",
+"darkgreen", "Temp", "BLOODT_3/3",
+"blue", "BP", "BP",
+"blue", "BP", " BP",
+"pink", "noise", "BW noise, signal 0",
+"pink", "noise", "BW noise, signal 1",
+"darkred", "CO", "CO",
+"darkred", "CO", "CO_1/2",
+"darkred", "CO", "CO_1/3",
+"darkred", "CO", "CO_2/2",
+"darkred", "CO", "CO_2/3",
+"darkred", "CO", "CO_3/3",
+"purple", "CO2", "C02",
+"blue", "BP", "CVP",
+"blue", "BP", "CVP_1/2",
+"blue", "BP", "CVP_1/3",
+"blue", "BP", "CVP_2/2",
+"blue", "BP", "CVP_2/3",
+"blue", "BP", "CVP_3/3",
+"red", "ECG", "CC5",
+"red", "ECG", "chan 1",
+"red", "ECG", "chan 2",
+"red", "ECG", "chan 3",
+"red", "ECG", "CM2",
+"red", "ECG", "CM4",
+"red", "ECG", "CM5",
+"purple", "CO2", "Co2",
+"purple", "CO2", "CO2",
+"purple", "CO2", "CO2^M ",
+"red", "ECG", "CS12",
+"red", "ECG", "CS34",
+"red", "ECG", "CS56",
+"red", "ECG", "CS78",
+"red", "ECG", "CS90",
+"blue", "BP", "CVP",
+"blue", "BP", "CVP 3",
+"red", "ECG", "D3",
+"red", "ECG", "D4",
+"red", "ECG", "ECG",
+"red", "ECG", " ECG",
+"red", "ECG", "ECG0",
+"red", "ECG", "ECG1",
+"red", "ECG", "ECG 1",
+"red", "ECG", "ECG 2",
+"red", "ECG", "ECG 3",
+"red", "ECG", "ECG AVF",
+"red", "ECG", "ECG       [ECG1]",
+"red", "ECG", "ECG F",
+"red", "ECG", "ECG I",
+"red", "ECG", "ECG II",
+"red", "ECG", "ECG III",
+"red", "ECG", "ECG lead 1",
+"red", "ECG", "ECG lead 2",
+"red", "ECG", "ECG lead 3",
+"red", "ECG", "ECG Lead AVF",
+"red", "ECG", "ECG lead AVL",
+"red", "ECG", "ECG lead I",
+"red", "ECG", "ECG Lead I",
+"red", "ECG", "ECG lead II",
+"red", "ECG", "ECG lead II ",
+"red", "ECG", "ECG LeadII",
+"red", "ECG", "ECG Lead II",
+"red", "ECG", "ECG lead III",
+"red", "ECG", "ECG Lead III",
+"red", "ECG", "ECG lead V",
+"red", "ECG", "ECG Lead V",
+"red", "ECG", "ECG Lead V ",
+"red", "ECG", "ECG Lead V3",
+"red", "ECG", "ECG Lead V4",
+"red", "ECG", "ECG lead V5",
+"red", "ECG", "ECG Lead V5",
+"red", "ECG", "ECG lead V6",
+"red", "ECG", "ECG MCL",
+"red", "ECG", "ECG signal 0",
+"red", "ECG", "ECG signal 1",
+"red", "ECG", "ECG V",
+"red", "ECG", "ECG V3",
+"red", "ECG", "ECG V Lead",
+"grey", "Annot", "EDF Annotations",
+"yellow", "EEG", "EEG",
+"yellow", "EEG", "EEG C3-A2 [C3A2]",
+"yellow", "EEG", "EEG (C3-O1)",
+"yellow", "EEG", "EEG (C4-A1)",
+"yellow", "EEG", "EEG C4-A1 [C4A1]",
+"yellow", "EEG", "EEG Fpz-Cz",
+"yellow", "EEG", "EEG (O2-A1)",
+"yellow", "EEG", "EEG Pz-Oz",
+"yellow", "EEG", "EEG(sec)",
+"orange", "EMG", "EMG",
+"orange", "EMG", "EMG-Chin  [EMYG]",
+"orange", "EMG", "EMG submental",
+"orange", "EMG", "EMG Submental",
+"pink", "noise", "EM noise, signal 0",
+"pink", "noise", "EM noise, signal 1",
+"lightblue", "EOG", "EOG",
+"lightblue", "EOG", "EOG E1-A1 [EOGL]",
+"lightblue", "EOG", "EOG E2-A1 [EOGR]",
+"lightblue", "EOG", "EOG horizontal",
+"lightblue", "EOG", "EOG(L)",
+"lightblue", "EOG", "EOG(R)",
+"lightblue", "EOG", "EOG (right)",
+"red", "ECG", "E-S",
+"grey", "Annot", "Event marker",
+"green", "Resp", "Flow      [AFLO]",
+"grey", "Annot", "Hypnogram",
+"red", "ECG", "i",
+"red", "ECG", "I",
+"red", "ECG", "I ",
+"red", "ECG", "I+",
+"blue", "BP", "ICP",
+"grey", "Annot", "ID+Sync+Error",
+"red", "ECG", "ii",
+"red", "ECG", "II",
+"red", "ECG", "II ",
+"red", "ECG", "II+",
+"red", "ECG", "iii",
+"red", "ECG", "III",
+"red", "ECG", "III ",
+"red", "ECG", "III+",
+"blue", "BP", "LAP",
+"red", "ECG", "lead I",
+"red", "ECG", "lead II",
+"red", "ECG", "lead V",
+"pink", "noise", "MA noise, signal 0",
+"pink", "noise", "MA noise, signal 1",
+"red", "ECG", "MCL1",
+"red", "ECG", "MCL1 ",
+"red", "ECG", "MCL1+",
+"red", "ECG", "ML2",
+"red", "ECG", "ML5",
+"red", "ECG", "MLI",
+"red", "ECG", "MLII",
+"red", "ECG", "MLIII",
+"red", "ECG", "mod.V1",
+"red", "ECG", "MV2",
+"red", "ECG", "MV2   ",
+"blue", "BP", "P1",
+"blue", "BP", "P1 Dias",
+"blue", "BP", "P1 Mean",
+"blue", "BP", "P1 Sys",
+"blue", "BP", "PA",
+"blue", "BP", "PAP",
+"blue", "BP", "PAP_1/2",
+"blue", "BP", "PAP_2/2",
+"blue", "BP", "PAP ",
+"blue", "BP", "PAP Dias",
+"blue", "BP", "PAP Mean",
+"blue", "BP", "PAP Sys",
+"blue", "BP", "PAP 2",
+"blue", "BP", "PAWP",
+"blue", "BP", "PAWP_1/2",
+"blue", "BP", "PAWP_1/3",
+"blue", "BP", "PAWP_2/2",
+"blue", "BP", "PAWP_2/3",
+"blue", "BP", "PAWP_3/3",
+"darkblue", "PLETH", "PLETH",
+"darkblue", "PLETH", "PLETH ",
+"grey", "Pos", "Position",
+"orangered", "HR", "HR",
+"orangered", "HR", "HR_1/2",
+"orangered", "HR", "HR_1/3",
+"orangered", "HR", "HR_2/2",
+"orangered", "HR", "HR_2/3",
+"orangered", "HR", "HR_3/3",
+"orangered", "HR", "PR",
+"blue", "BP", "Pressure",
+"blue", "BP", "Pressure ",
+"blue", "BP", "Pressure1",
+"blue", "BP", "Pressure 1",
+"blue", "BP", "Pressure 2",
+"blue", "BP", "Pressure 3",
+"blue", "BP", "Pressure 4",
+"orangered", "HR", "Pulse",
+"orangered", "HR", "PULSE",
+"orangered", "HR", "PULSE_1/2",
+"orangered", "HR", "PULSE_1/3",
+"orangered", "HR", "PULSE_2/2",
+"orangered", "HR", "PULSE_2/3",
+"orangered", "HR", "PULSE_3/3",
+"orangered", "HR", "PVC Rate per Minute",
+"orangered", "HR", "PVC Rate per Minute_1/2",
+"orangered", "HR", "PVC Rate per Minute_1/3",
+"orangered", "HR", "PVC Rate per Minute_2/3",
+"orangered", "HR", "PVC Rate per Minute_3/3",
+"blue", "BP", "RAP",
+"green", "Resp", "RESP",
+"green", "Resp", "RESP_1/2",
+"green", "Resp", "RESP_1/3",
+"green", "Resp", "RESP_2/2",
+"green", "Resp", "RESP_2/3",
+"green", "Resp", "RESP_3/3",
+"green", "Resp", " RESP",
+"green", "Resp", "RESP ",
+"green", "Resp", "Resp A",
+"green", "Resp", "Resp (abdomen)",
+"green", "Resp", "Resp (abdominal)",
+"green", "Resp", "Resp C",
+"green", "Resp", "Resp (chest)",
+"green", "Resp", "Resp Imp",
+"green", "Resp", "Resp. Imp.",
+"green", "Resp", "Resp.Imp.",
+"green", "Resp", "RESP IMP",
+"green", "Resp", "Resp Inp.",
+"green", "Resp", "Resp N",
+"green", "Resp", "Resp (nasal)",
+"green", "Resp", "Resp oro-nasal",
+"green", "Resp", "Resp (sum)",
+"darkred", "O2", "SaO2",
+"darkred", "O2", "SaO2      [OSAT]",
+"darkred", "O2", "SO2",
+"grey", "Sound", "Sound",
+"darkred", "O2", "SpO2",
+"darkred", "O2", "SpO2_1/2",
+"darkred", "O2", "SpO2_1/3",
+"darkred", "O2", "SpO2_2/2",
+"darkred", "O2", "SpO2_2/3",
+"darkred", "O2", "SpO2_3/3",
+"green", "Resp", "Sum",
+"magenta", "SV", "SV",
+"darkgreen", "Temp", "Temp body",
+"green", "Resp", "Thorax_1",
+"green", "Resp", "Thorax_2",
+"green", "Resp", "Thorax    [CHMV]",
+"green", "Resp", "THOR RES",
+"blue", "BP", "UAP",
+"blue", "BP", "UAP Dias",
+"blue", "BP", "UAP Mean",
+"blue", "BP", "UAP Sys",
+"red", "ECG", "V",
+"red", "ECG", "V ",
+"red", "ECG", "V+",
+"red", "ECG", "v1",
+"red", "ECG", "V1",
+"red", "ECG", "V1-V2",
+"red", "ECG", "v2",
+"red", "ECG", "V2",
+"red", "ECG", "V2-V3",
+"red", "ECG", "v3",
+"red", "ECG", "V3",
+"red", "ECG", "v4",
+"red", "ECG", "V4",
+"red", "ECG", "V4-V5",
+"red", "ECG", "v5",
+"red", "ECG", "V5",
+"red", "ECG", "v6",
+"red", "ECG", "V6",
+"red", "ECG", "vx",
+"red", "ECG", "vy",
+"red", "ECG", "vz",
+NULL,   NULL,   NULL
+};
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/app/wfdbmap.c wfdb-10.5.10/app/wfdbmap.c
--- wfdb-10.5.9/app/wfdbmap.c	1969-12-31 19:00:00.000000000 -0500
+++ wfdb-10.5.10/app/wfdbmap.c	2011-11-15 15:19:40.000000000 -0500
@@ -0,0 +1,472 @@
+/* file: wfdbmap.c	G. Moody       	22 March 2009
+			Last revised:	15 November 2011
+
+-------------------------------------------------------------------------------
+wfdbmap: generates a 'plt' script to make a PostScript map of a WFDB record
+Copyright (C) 2009-2011 George B. Moody
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA.
+
+You may contact the author by e-mail (george@mit.edu) or postal mail
+(MIT Room E25-505A, Cambridge, MA 02139 USA).  For updates to this software,
+please visit PhysioNet (http://www.physionet.org/).
+_______________________________________________________________________________
+
+The file signal-colors.h in this directory defines the colors used by wfdbmap.
+*/
+
+#include <stdio.h>
+#include <wfdb/wfdb.h>
+#include <wfdb/wfdblib.h>
+#include <wfdb/ecgcodes.h>
+#include <wfdb/ecgmap.h>
+
+char *pname;
+WFDB_Anninfo *ai = NULL;
+WFDB_Siginfo *si = NULL;
+int mflag = 0;
+int spm;
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+    char *record = NULL, *prog_name();
+    int i, j, length, **map = NULL, nann = 0, nsig;
+    void help();
+    void map_sig(char *record, WFDB_Siginfo *si, int nsig,int **map,int length);
+    void map_ann(char *record, WFDB_Anninfo *ai, int nann,int **map,int length);
+    void write_map(int **map, int nsig, int nann, int length);
+    void write_script(int **map, int nsig, int nann, int length);
+
+    pname = prog_name(argv[0]);
+
+    /* Interpret command-line options. */
+    for (i = 1; i < argc; i++) {
+	if (*argv[i] == '-') switch (*(argv[i]+1)) {
+	  case 'a':	/* annotators follow */
+	    if (++i >= argc) {
+		(void)fprintf(stderr, "%s: annotators must follow -a\n",
+			      pname);
+		exit(1);
+	    }
+	    /* how may annotators are there? */
+	    for (j = i; j < argc && *argv[j] != '-'; j++)
+		;
+	    nann = j - i;
+	    /* allocate *ai and initialize it */
+	    if (nann > 0) {
+		if ((ai = malloc(nann * sizeof(WFDB_Anninfo))) == NULL) {
+		    fprintf(stderr, "%s: insufficient memory\n", pname);
+		    exit(2);
+		}
+		for (j = 0; j < nann; j++) {
+		    ai[j].name = argv[i++];
+		    ai[j].stat = WFDB_READ;
+		}
+	    }
+	    i--;
+	    break;
+	  case 'h':	/* print usage summary and quit */
+	    help();
+	    exit(0);
+	    break;
+          case 'm':     /* print map only */
+	    mflag = 1;
+	    break;
+	  case 'r':	/* input record name follows */
+	    if (++i >= argc) {
+		(void)fprintf(stderr,
+			      "%s: input record name must follow -r\n",
+			      pname);
+		exit(1);
+	    }
+	    record = argv[i];
+	    break;
+	  default:
+	    (void)fprintf(stderr, "%s: unrecognized option %s\n",
+			  pname, argv[i]);
+	    exit(1);
+	}
+	else {
+	    (void)fprintf(stderr, "%s: unrecognized argument %s\n",
+			  pname, argv[i]);
+	    exit(1);
+	}
+    }
+    if (record == NULL) {
+	help();
+	exit(1);
+    }
+
+    nsig = isigopen(record, NULL, 0);
+    if (nsig > 0) {
+	if ((si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) {
+	    fprintf(stderr, "%s: insufficient memory\n", pname);
+	    if (ai) { wfdbquit(); free(ai); }
+	    exit(2);
+	}
+	if ((nsig = isigopen(record, si, nsig)) < 0)
+	    nsig = 0;
+    }
+    spm = strtim("60");
+    length = (strtim("e") + (spm-1))/spm;  /* number of minutes in record */
+
+    if (length < 1 && nsig > 0) {
+        /* calculate the length of the record from the signal file size */
+        char *p;
+        double fs = 0;
+	FILE *ifile;
+	long bpm;
+
+        for (i = 0; i < nsig && si[i].group == 0; i++)
+	  switch (si[i].fmt) {
+	  case 8:
+	  case 80:  fs += si[i].spf; break;
+	  case 310:
+	  case 311: fs += 1.33333333*si[i].spf; break;
+	  case 212: fs += 1.5*si[i].spf; break;
+	  default:  fs += 2*si[i].spf; break;
+	  }
+	bpm = fs * spm + 0.5;  /* bytes per minute */
+	p = wfdbfile(si[i].fname, NULL);
+	ifile = fopen(p, "r");
+	fseek(ifile, 0L, SEEK_END);
+	length = ftell(ifile)/bpm;
+	fclose(ifile);
+    }
+
+    if (length < 1) {	/* try to get length from annotation file(s) */
+        int alen;
+        WFDB_Annotation annot;
+	WFDB_Time t;
+
+        for (i = 0; i < nann; i++) {
+	    if (annopen(record, &ai[i], 1) < 0) continue;
+	    while (getann(0, &annot) >= 0)
+	        t = annot.time;
+	    alen = (t + (spm-1))/spm;
+	    if (alen > length) length = alen;
+	}
+    }
+
+    if (length > 60000) /* 1000 hours > 41 days */
+        length = 60000;		/* truncate extremely long records */
+
+    if (length < 1) {
+	fprintf(stderr, "%s: can't map record %s (length unspecified)\n",
+		pname, record);
+	exit(1);
+    }
+
+    if ((map = malloc((nsig + 4*nann) * sizeof(int *))) == NULL) {
+	fprintf(stderr, "%s: insufficient memory\n", pname);
+	wfdbquit();
+	if (ai) free(ai);
+	if (si) free(si);
+	exit(2);
+    }
+    for (i = 0; i < nsig + 4*nann; i++)
+	if ((map[i] = calloc(length, sizeof(int))) == NULL) {
+	    fprintf(stderr, "%s: insufficient memory\n", pname);
+	    while (--i > 0)
+		if (map[i]) free(map[i]);
+	    free(map);
+	    wfdbquit();
+	    if (ai) free(ai);
+	    if (si) free(si);
+	    exit(2);
+	}
+
+    if (nsig > 0) map_sig(record, si, nsig, map, length);
+    if (nann > 0) map_ann(record, ai, nann, &map[nsig], length);
+
+    if (mflag) {
+	printf("T");
+	for (i = 0; i < nsig; i++)
+	    printf("\t%s", si[i].desc);
+	for (i = 0; i < nann; i++)
+	    printf("\t%s\tQRS\tEctopic\tVE", ai[i].name);
+	printf("\n");
+	write_map(map, nsig, nann, length);
+    }
+    else
+	write_script(map, nsig, nann, length);
+	
+    for (i = 0; i < nsig + 4*nann; i++)
+	free(map[i]);
+    free(map);
+    wfdbquit();
+    if (ai) free(ai);
+    if (si) free(si);
+
+    exit(0);
+}
+
+void map_sig(char *record, WFDB_Siginfo *si, int nsig, int **map, int length)
+{
+    if (si[0].nsamp == strtim("e") || si[0].nsamp != 0) {
+	/* fixed-layout record */
+        int i, t;
+	for (i = 0; i < nsig; i++)
+	    for (t = 0; t < length; t++)
+		map[i][t] = 1;
+    }
+    else {	/* variable-layout record */
+	char buf[256], *d, *p, *q, *r, *hfname, *shfname;
+	long m, m0, mf, spm = strtim("60"), t = 0, tf;
+	WFDB_FILE *ifile, *sfile;
+
+	p = wfdbfile("hea", record);
+	hfname = calloc(strlen(p) + 1, 1);
+	strcpy(hfname, p);
+	if ((ifile = wfdb_fopen(hfname, "r")) == NULL) {
+	    fprintf(stderr, "%s: can't open %s\n", pname, hfname);
+	    free(hfname);
+	    return;
+	}
+	for (d = p + strlen(p); d > p; d--)
+	    if (*(d-1) == '/') {
+		*d = '\0';
+		break;
+	    }
+	shfname = calloc(strlen(hfname) + 16, 1);
+	strcpy(shfname, p);
+	d = shfname + strlen(shfname);   /* d points to first char after '/' */
+	wfdb_fgets(buf, sizeof(buf), ifile);  /* read and ignore two lines */
+	wfdb_fgets(buf, sizeof(buf), ifile);
+
+	m0 = 0;
+	while (wfdb_fgets(buf, sizeof(buf), ifile)) {/* read a segment desc */ 
+	    char *tp;
+
+	    if (buf[0] == '~') {  /* segment is null (all signals off) */
+		t += atol(buf+2);
+		m0 = t/spm;
+		continue;
+	    }
+	    for (tp = buf+1; *tp != ' '; tp++)
+		; 
+	    *tp = '\0';
+	    tf = t + atol(tp+1);
+	    if ((mf = tf/spm) > length) mf = length;
+	    sprintf(d, "%s.hea", buf);
+	    if (sfile = wfdb_fopen(shfname, "r")) {/* open the segment header */
+		char sbuf[256];
+		int i;
+
+		wfdb_fgets(sbuf, sizeof(sbuf), sfile);/* read & ignore a line */
+      
+		while ((p = wfdb_fgets(sbuf, sizeof(sbuf), sfile)) &&
+		       *sbuf != '#') {
+		    /* signal description line */
+		    for (q = sbuf, i = 0; *q; q++)
+			if (*q == ' ' && ++i == 8) break;
+		    q++;
+		    *(q + strlen(q) - 2) = '\0';
+		    for (i = 0; i < nsig; i++)
+			if (strcmp(si[i].desc, q) == 0)
+			    for (m = m0; m < mf; m++)
+				map[i][m] = 1;
+		}
+		wfdb_fclose(sfile);
+		t = tf;
+		m0 = t/spm;
+	    }
+	}
+	wfdb_fclose(ifile);
+	free(shfname);
+	free(hfname);
+    }
+}
+
+int *namax;
+
+void map_ann(char *record, WFDB_Anninfo *ai, int nann, int **map, int length)
+{
+    int i;
+
+    namax = malloc(nann * sizeof(int));
+    wfdbquiet();   /* suppress warnings if an annotator can't be opened */
+    for (i = 0; i < nann; i++) {
+	char tstring[10];
+	int minutes, *na, *nq, *ne, *nv;
+	WFDB_Annotation annot;
+	WFDB_Time end_of_epoch;
+
+	na = &map[4*i][0];
+	namax[i] = 1;
+
+	/* Open the annotators one at a time, and do not quit if any fail
+	   to open. */
+	if (annopen(record, &ai[i], 1) < 0) continue;
+	minutes = end_of_epoch = 0;
+	iannsettime(1L);
+	while (getann(0, &annot) >= 0) {
+	    if (annot.time > end_of_epoch) {
+	        if (*na > namax[i]) namax[i] = *na;
+		minutes = annot.time/spm;
+		na = &map[4*i][minutes];
+		nq = &map[4*i + 1][minutes];
+		ne = &map[4*i + 2][minutes];
+		nv = &map[4*i + 3][minutes];
+		if (++minutes > length)
+		    break;	/* stop at the end of the record */
+		sprintf(tstring, "%d", 60*minutes);
+		end_of_epoch = strtim(tstring);
+	    }
+	    switch (annot.anntyp) {
+	    case PVC:
+	    case FUSION:
+	    case VESC:
+	    case RONT:
+	    case FLWAV:	(*nv)++;	/* fall through, no break! */
+	    case APC:
+	    case ABERR:
+	    case NPC:
+	    case SVPB:
+	    case NESC:
+	    case AESC:
+	    case SVESC:	(*ne)++;	/* fall through, no break! */
+	    case NORMAL:
+	    case LBBB:
+	    case RBBB:
+	    case PACE:
+	    case UNKNOWN:
+	    case BBB:
+	    case LEARN:
+	    case PFUS:	(*nq)++;	/* fall through, no break! */
+	    default:	(*na)++; break;
+	    }
+	}
+	if (*na > namax[i]) namax[i] = *na;
+    }
+    return;
+}
+
+void write_map(int **map, int nsig, int nann, int length)
+{
+    int i, imax = nsig + 4*nann - 1, t;
+
+    for (t = 0; t < length; t++) {
+	if (mflag == 0) printf("%d\t0\t", t); /* x0, y0 for histogram plots */
+	printf("%d\t", t+1);
+	for (i = 0; i < imax; i++)
+	    printf("%d\t", map[i][t]);
+	printf("%d\n", map[i][t]);
+    }
+}
+
+#include "signal-colors.h"
+
+char *color(char *type)
+{
+    int i;
+
+    for (i = 0; ctab[i].name != NULL; i++)
+	if (strcmp(type, ctab[i].name) == 0) return (ctab[i].color);
+    return ("grey");
+}
+
+void write_script(int **map, int nsig, int nann, int length)
+{
+  char *p, tstring[2][30];
+    double ylow, ymax;
+    int i, j;
+    WFDB_Time tf = strtim("e");
+
+    strcpy(tstring[0], timstr(0));
+    for (p = tstring[0]; *p == ' '; p++)
+        ;
+    if (tf) strcpy(tstring[1], timstr(-tf));
+    else sprintf(tstring[1], "%d:%02d:00", length/60, length%60);
+
+    ymax = 2*(nsig + 2*nann + 1);
+    ylow = 0.01 * ymax;
+
+    printf("#! /bin/sh\n"
+	   "cat >map.txt <<EOF\n");
+    write_map(map, nsig, nann, length);
+    printf("EOF\n\n");
+
+    printf("MAP=map.txt\n"
+	   "FDEF=\"-sf l Fh,P8\"\n"
+	   "LDEF=\"-setxy -l %g 0 RB\"\n"
+	   "WDEF=\"-W .048 .1 .982 1\"\n"
+	   "XDEF=\"-X 0 %d\"\n"
+	   "OPT=\"$FDEF $XDEF $WDEF $LDEF\"\n",
+	   -0.005*length, length);
+    
+    printf("lwplt $WDEF $XDEF -Y 0 %g -stxy -sf l Fh-b,P12", ymax);
+    printf(" -l 0 %g LT \"%s\"", ylow, p);
+    printf(" -l %g %g CT \"time\"", 0.5*length, ylow);
+    printf(" -l %d %g RT \"%s\"\n\n", length, ylow, tstring[1]);
+
+    for (i = 0; i < nann; i++) {
+	j = nsig + i;
+	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT %s\n",
+	       j+3*i+3, "grey", 0.5*namax[i]*(2*(j+i+2) - ymax),
+	       0.5*namax[i]*2*(j+i+2), ai[i].name);
+	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT %s\n",
+	       j+3*i+4, "black", 0.5*namax[i]*(2*(j+i+2) - ymax),
+	       0.5*namax[i]*2*(j+i+2), ai[i].name);
+	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT %s\n",
+	       j+3*i+5, "blue", 0.5*namax[i]*(2*(j+i+2) - ymax),
+	       0.5*namax[i]*2*(j+i+2), ai[i].name);
+	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT %s\n",
+	       j+3*i+6, "red", 0.5*namax[i]*(2*(j+i+2) - ymax),
+	       0.5*namax[i]*2*(j+i+2), ai[i].name);
+    }
+
+    for (i = 0; i < nsig; i++)
+	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT \"%s\"\n",
+	       i+3, color(si[i].desc), 2.*(i+1) - ymax,
+	       2.*(i+1), si[i].desc);
+}
+
+char *prog_name(s)
+char *s;
+{
+    char *p = s + strlen(s);
+
+#ifdef MSDOS
+    while (p >= s && *p != '\\' && *p != ':') {
+	if (*p == '.')
+	    *p = '\0';		/* strip off extension */
+	if ('A' <= *p && *p <= 'Z')
+	    *p += 'a' - 'A';	/* convert to lower case */
+	p--;
+    }
+#else
+    while (p >= s && *p != '/')
+	p--;
+#endif
+    return (p+1);
+}
+
+static char *help_strings[] = {
+ "usage: %s -r RECORD -a ANNOTATOR [OPTIONS ...]\n",
+ "where RECORD and ANNOTATOR specify the input, and OPTIONS may include:",
+ " -h       print this usage summary",
+NULL
+};
+
+void help()
+{
+    int i;
+
+    (void)fprintf(stderr, help_strings[0], pname);
+    for (i = 1; help_strings[i] != NULL; i++)
+	(void)fprintf(stderr, "%s\n", help_strings[i]);
+}
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/app/wfdbsignals.c wfdb-10.5.10/app/wfdbsignals.c
--- wfdb-10.5.9/app/wfdbsignals.c	1969-12-31 19:00:00.000000000 -0500
+++ wfdb-10.5.10/app/wfdbsignals.c	2011-11-15 14:07:40.000000000 -0500
@@ -0,0 +1,89 @@
+/* file: wfdbsignals.c	G. Moody	  June 1989
+			Last revised:   15 November 2011
+
+-------------------------------------------------------------------------------
+wfdbdesc: List signals in a WFDB record
+Copyright (C) 1989-2011 George B. Moody
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA.
+
+You may contact the author by e-mail (george@mit.edu) or postal mail
+(MIT Room E25-505A, Cambridge, MA 02139 USA).  For updates to this software,
+please visit PhysioNet (http://www.physionet.org/).
+_______________________________________________________________________________
+
+This program is a drastically pruned version of wfdbdesc.
+
+*/
+
+#include <stdio.h>
+#include <wfdb/wfdb.h>
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+    char *info, *p, *pname, *prog_name();
+    int i, msrec = 0, nsig;
+    FILE *ifile;
+    WFDB_Siginfo *s;
+    WFDB_Time t;
+
+    pname = prog_name(argv[0]);
+    if (argc < 2) {
+        (void)fprintf(stderr, "usage: %s RECORD [-readable]\n", pname);
+        exit(1);
+    }
+    /* Discover the number of signals defined in the header. */
+    if ((nsig = isigopen(argv[1], NULL, 0)) < 0) exit(2);
+
+    /* Allocate storage for nsig signal information structures. */
+    if (nsig > 0 && (s = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) {
+	fprintf(stderr, "%s: insufficient memory\n", pname);
+	exit(2);
+    }
+
+    /* If the `-readable' option is given, report only on signals which can
+       be opened.  Otherwise, report on all signals named in the header file,
+       without attempting to open them. */
+    if (nsig > 0 && argc > 2 &&
+	strncmp(argv[2], "-readable", strlen(argv[2])) == 0)
+	nsig = isigopen(argv[1], s, nsig);
+    else if (nsig > 0)
+	nsig = isigopen(argv[1], s, -nsig);
+
+    for (i = 0; i < nsig; i++)
+        (void)printf("%s\n", s[i].desc);
+    exit(0);	/*NOTREACHED*/
+}
+
+char *prog_name(s)
+char *s;
+{
+    char *p = s + strlen(s);
+
+#ifdef MSDOS
+    while (p >= s && *p != '\\' && *p != ':') {
+	if (*p == '.')
+	    *p = '\0';		/* strip off extension */
+	if ('A' <= *p && *p <= 'Z')
+	    *p += 'a' - 'A';	/* convert to lower case */
+	p--;
+    }
+#else
+    while (p >= s && *p != '/')
+	p--;
+#endif
+    return (p+1);
+}
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/doc/wag-src/maketoc-tex.sh wfdb-10.5.10/doc/wag-src/maketoc-tex.sh
--- wfdb-10.5.9/doc/wag-src/maketoc-tex.sh	2002-10-29 15:29:41.000000000 -0500
+++ wfdb-10.5.10/doc/wag-src/maketoc-tex.sh	2011-11-16 14:08:19.000000000 -0500
@@ -1,6 +1,6 @@
 #! /bin/sh
 # file: maketoc-tex.sh		G. Moody	29 October 2002
-#
+#				Last revised:	16 November 2011
 # Generate the table of contents and appendices for the WFDB Applications Guide
 
 prep()
@@ -17,7 +17,7 @@
 {
     P=`grep '%%Pages: ' <wag2.ps | cut -c 10-`
     case $P in
-      *[13579]) cat blankpage >>wag2.ps; P=`expr $P + 2`;;
+      *[13579]) cat wag2.ps blankpage >wag2b.ps; P=`expr $P + 2`;;
       *) P=`expr $P + 1`;;
     esac
     sed s/FIRSTPAGE/$P/ <install0.tex >install.tex
@@ -25,7 +25,7 @@
     N=`grep '%%Pages: ' <wag3.ps | cut -c 10-`
     Q=`expr $P + $N`
     case $Q in
-      *[02468]) cat blankpage >>wag3.ps; Q=`expr $Q + 1`;;
+      *[02468]) cat wag3.ps blankpage >wag3b.ps; Q=`expr $Q + 1`;;
     esac
     sed s/FIRSTPAGE/$Q/ <eval0.tex >eval.tex
     make wag4.ps
@@ -45,6 +45,15 @@
 head -$N1 <toc.out | ./maketoclines
 
 appendices >>toc-log.$$ 2>&1
+if [ -e wag2b.ps ]
+then
+    mv -f wag2b.ps wag2.ps
+fi
+if [ -e wag3b.ps ]
+then
+    mv -f wag3b.ps wag3.ps
+fi
+
 
 cat <<EOF
 
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/doc/wag-src/wabp.1 wfdb-10.5.10/doc/wag-src/wabp.1
--- wfdb-10.5.9/doc/wag-src/wabp.1	2009-01-07 15:11:52.000000000 -0500
+++ wfdb-10.5.10/doc/wag-src/wabp.1	2011-11-07 12:20:24.000000000 -0500
@@ -1,4 +1,4 @@
-.TH WABP 1 "7 January 2009" "WFDB 10.4.12" "WFDB Applications Guide"
+.TH WABP 1 "7 November 2011" "WFDB 10.5.10" "WFDB Applications Guide"
 .SH NAME
 wabp \- arterial blood pressure (ABP) pulse detector
 .SH SYNOPSIS
@@ -71,7 +71,7 @@
 .br
 The output annotations may be read using (for example):
 .br
-	\fBrdann -a slpdb/slp60 -r 100\fR
+	\fBrdann -r slpdb/slp60 -a wabp\fR
 .PP
 .br
 
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/doc/wag-src/wfdbmap.1 wfdb-10.5.10/doc/wag-src/wfdbmap.1
--- wfdb-10.5.9/doc/wag-src/wfdbmap.1	1969-12-31 19:00:00.000000000 -0500
+++ wfdb-10.5.10/doc/wag-src/wfdbmap.1	2011-11-15 15:31:33.000000000 -0500
@@ -0,0 +1,45 @@
+.TH WFDBMAP 1 "15 November 2011" "WFDB 10.5.10" "WFDB Applications Guide"
+.SH NAME
+wfdbmap \- make a synoptic map of a WFDB record
+.SH SYNOPSIS
+\fBwfdbmap -r\fR \fIrecord\fR [ \fB-a\fR \fIannotator \fR ...  ]
+.br
+\fBmap-record -r\fR \fIrecord\fR [ \fB-a\fR \fIannotator \fR ...  ]
+.SH DESCRIPTION
+.PP
+\fBwfdbmap\fR generates a shell script containing commands and embedded
+data for creating a synoptic map of a WFDB-compatible \fIrecord\fR, optionally
+including one or more associated sets of annotations (specified by one or more
+\fIannotator\fR names following the \fB-a\fR option).  When the script is run,
+it creates a PostScript-format 'map' of the WFDB record and its annotations,
+using \fBlwplt\fR from the \fBplt\fR(1) package.  The maps displayed by the
+PhysioBank ATM are created in this way, with an additional conversion of the
+PostScript map to browser-compatible PNG format using \fBconvert\fR from
+ImageMagick (http://www.imagemagick.org/).
+.PP
+\fBmap-record\fR is a shell script that illustrates how \fBwfdbmap\fR and
+(indirectly) \fBplt\fR are used to create a map, and how to convert
+the PostScript map into a PNG-format map using \fBconvert\fR.
+.PP
+For example, to make a map of mitdb/200 and its associated 'atr' annotations,
+run the command:
+.IP
+\fBmap-record mitdb/200 -a atr\fR
+.PP
+The outputs of this command are \fB200.ps\fR and \fB200.png\fR.  If other
+annotation files are available, their annotator names can be given as
+additional command-line arguments:
+.IP
+\fBmap-record \fIrecord\fB -a \fIann1 ann2 ann3 ...
+.SH ENVIRONMENT
+.PP
+It may be necessary to set and export the shell variable \fBWFDB\fR (see
+\fBsetwfdb\fR(1)).
+.SH SEE ALSO
+\fBplt\fR(1), \fBsetwfdb\fR(1)
+.SH AUTHOR
+George B. Moody (george@mit.edu)
+.SH SOURCE
+http://www.physionet.org/physiotools/wfdb/app/wfdbmap.c
+http://www.physionet.org/physiotools/wfdb/app/signal-colors.h
+http://www.physionet.org/physiotools/wfdb/app/map-record
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/doc/wpg-src/wpg0.tex wfdb-10.5.10/doc/wpg-src/wpg0.tex
--- wfdb-10.5.9/doc/wpg-src/wpg0.tex	2011-03-12 13:07:28.000000000 -0500
+++ wfdb-10.5.10/doc/wpg-src/wpg0.tex	2011-11-15 15:49:06.000000000 -0500
@@ -837,8 +837,8 @@
 import wfdb, sys
 
 def main(argv):
-    siarray = wfdb.WFDB_SiginfoArray(2)
-    if wfdb.isigopen("100s", siarray.cast(), 2) < 2: sys.exit(1)
+    siarray = wfdb.isigopen("100s")
+    if siarray.nsig < 2: sys.exit(1)
     v = wfdb.WFDB_SampleArray(2)
     for i in range(0,10):
         if wfdb.getvec(v.cast()) < 0: sys.exit(2)
@@ -8990,6 +8990,38 @@
 
 @unnumberedsec WFDB 10.5
 
+@unnumberedsubsec Changes in version 10.5.10 (15 November 2011)
+
+The WFDB library function @code{isigopen()}, in @file{lib/signal.c}, searches
+each component of the WFDB path for the signal file(s) named in the associated
+header file, until a match is found.  Since signal files are usually located in
+the same directories as header files, they can be located most quickly by
+looking first in those directories.  Thanks to David Brooks for suggesting this
+optimization and for a sample implementation.
+
+Attempts to set the default size for HTTP range requests (using the environment
+variable @code{WFDB_PAGESIZE}) were ignored in previous versions of the WFDB
+library when compiled with libcurl.  Thanks again to David for noting this
+limitation, which has been eliminated in this release by a change in
+@code{www_init()} (in @file{lib/wfdbio.c}).
+
+@unnumberedsubsec Changes in version 10.5.9 (10 September 2011)
+
+When an application passes an array containing @code{WFDB_INVALID_SAMPLE}
+values to @code{putvec()}, the function translates these into the corresponding
+invalid-sample sentinel values used by the file format.  (This is the inverse
+of the transformation done by @code{getvec()} and @code{getframe()}, so the
+effect is that at the application level, invalid samples are always represented
+by the value @code{WFDB_INVALID_SAMPLE}.)
+
+Previous versions of the library did not perform this transformation correctly
+for formats 80 and 160 (they used a value of zero rather than -128 or -32768,
+respectively.)  This bug was mainly an issue for programs such as @file{snip}
+and @file{xform} that read and modify existing data files.
+
+Thanks to Benjamin Moody for identifying these problems and providing patches
+to remedy them.
+
 @unnumberedsubsec Changes in version 10.5.8 (12 March 2011)
 
 Previous versions of the WFDB library did not behave properly if
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/lib/signal.c wfdb-10.5.10/lib/signal.c
--- wfdb-10.5.9/lib/signal.c	2011-08-05 16:53:14.000000000 -0400
+++ wfdb-10.5.10/lib/signal.c	2011-11-07 10:09:56.000000000 -0500
@@ -1,10 +1,10 @@
 /* file: signal.c	G. Moody	13 April 1989
-			Last revised:  29 November 2010		wfdblib 10.5.6
+			Last revised:  7 November 2011		wfdblib 10.5.10
 WFDB library functions for signals
 
 _______________________________________________________________________________
 wfdb: a library for reading and writing annotated waveforms (time series data)
-Copyright (C) 1989-2010 George B. Moody
+Copyright (C) 1989-2011 George B. Moody
 
 This library is free software; you can redistribute it and/or modify it under
 the terms of the GNU Library General Public License as published by the Free
@@ -1890,6 +1890,7 @@
 
 FINT isigopen(char *record, WFDB_Siginfo *siarray, int nsig)
 {
+    char *filename, *fullname, *p;
     int navail, ngroups, nn;
     struct hsdata *hs;
     struct isdata *is;
@@ -1936,6 +1937,17 @@
 	return (navail);
     }
 
+    /* Save any directory prefix in record name and use this when looking for
+       signal files. */
+    fullname = calloc(strlen(record)+strlen(getwfdb()+2), sizeof(char));
+    strcpy(fullname, record);
+    filename = p = fullname;
+    while (*p) {
+	while (*p && *p != '/') ++p;
+	if (*p) filename = ++p;
+    }
+    *filename = '\0' ;
+
     /* Determine how many new signals we should attempt to open.  The caller's
        upper limit on this number is nsig, and the upper limit defined by the
        header is navail. */
@@ -1986,7 +1998,8 @@
 	if (hs->info.fmt == 0)
 	    ig->fp = NULL;	/* Don't open a file for a null signal. */
 	else { 
-	    ig->fp = wfdb_open(hs->info.fname, (char *)NULL, WFDB_READ);
+	    strcpy(filename, hs->info.fname);
+	    ig->fp = wfdb_open(fullname, (char *)NULL, WFDB_READ);
 	    /* Skip this group if the signal file can't be opened. */
 	    if (ig->fp == NULL) {
 	        SFREE(ig->buf);
@@ -2010,6 +2023,7 @@
 	}
 	g++;
     }
+    free(fullname);
 
     /* Produce a warning message if none of the requested signals could be
        opened. */
@@ -2032,7 +2046,6 @@
     gvc = ispfmax;	/* Initialize getvec's sample-within-frame counter. */
     nisig += s;		/* Update the count of open input signals. */
     nigroups += g;	/* Update the count of open input signal groups. */
-
     if (sigmap_init() < 0)
 	return (-1);
 
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/lib/wfdb.h wfdb-10.5.10/lib/wfdb.h
--- wfdb-10.5.9/lib/wfdb.h	2011-08-05 17:06:03.000000000 -0400
+++ wfdb-10.5.10/lib/wfdb.h	2011-11-16 14:51:34.000000000 -0500
@@ -32,7 +32,7 @@
 /* WFDB library version. */
 #define WFDB_MAJOR   10
 #define WFDB_MINOR   5
-#define WFDB_RELEASE 9
+#define WFDB_RELEASE 10
 #define WFDB_NETFILES 1	/* if 1, library includes code for HTTP, FTP clients */
 #define WFDB_NETFILES_LIBCURL 1
 
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/lib/wfdbio.c wfdb-10.5.10/lib/wfdbio.c
--- wfdb-10.5.9/lib/wfdbio.c	2010-12-16 19:04:25.000000000 -0500
+++ wfdb-10.5.10/lib/wfdbio.c	2011-11-07 10:09:32.000000000 -0500
@@ -1,10 +1,10 @@
 /* file: wfdbio.c	G. Moody	18 November 1988
-                        Last revised:	16 December 2010       wfdblib 10.5.7
+                        Last revised:	 7 November 2011       wfdblib 10.5.10
 Low-level I/O functions for the WFDB library
 
 _______________________________________________________________________________
 wfdb: a library for reading and writing annotated waveforms (time series data)
-Copyright (C) 1988-2010 George B. Moody
+Copyright (C) 1988-2011 George B. Moody
 
 This library is free software; you can redistribute it and/or modify it under
 the terms of the GNU Library General Public License as published by the Free
@@ -1214,6 +1214,10 @@
 static void www_init(void)
 {
     if (!www_done_init) {
+	char *p, version[20];
+
+	if ((p = getenv("WFDB_PAGESIZE")) && *p) page_size = atol(p);
+
 #if WFDB_NETFILES_LIBCURL
 	/* Initialize the curl "easy" handle. */
 	curl_global_init(CURL_GLOBAL_ALL);
@@ -1233,8 +1237,6 @@
 	   information from libcurl) */
 	/* curl_easy_setopt(curl_ua, CURLOPT_VERBOSE, 1L); */
 #else
-	char *p;
-	char version[20];
 
 #ifdef USEHTCACHE
 	char *cachedir = CACHEDIR;	/* root of the netfile data cache */
@@ -1245,7 +1247,6 @@
 	if ((p = getenv("WFDB_CACHESIZE")) && *p) cachesize = atoi(p);
 	if ((p = getenv("WFDB_CACHEENTRYSIZE")) && *p) entrysize = atoi(p);
 #endif
-	if ((p = getenv("WFDB_PAGESIZE")) && *p) page_size = atol(p);
 	sprintf(version, "%d.%d.%d", WFDB_MAJOR, WFDB_MINOR, WFDB_RELEASE);
 	HTProfile_newPreemptiveClient("WFDB", version);
 	HTAlert_setInteractive(NO);
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/MANIFEST wfdb-10.5.10/MANIFEST
--- wfdb-10.5.9/MANIFEST	2010-11-04 10:38:16.000000000 -0400
+++ wfdb-10.5.10/MANIFEST	2011-11-15 15:53:08.000000000 -0500
@@ -11,6 +11,7 @@
 app/Makefile
 app/Makefile.top
 app/Makefile.tpl
+app/map-record
 app/mfilt.c
 app/mrgann.c
 app/mxm.c
@@ -31,6 +32,7 @@
 app/setwfdb
 app/sigamp.c
 app/sigavg.c
+app/signal-colors.h
 app/signame.c
 app/signum.c
 app/skewedit.c
@@ -47,6 +49,8 @@
 app/wfdbcollate.c
 app/wfdb-config.c
 app/wfdbdesc.c
+app/wfdbmap.c
+app/wfdbsignals.c
 app/wfdbtime.c
 app/wfdbwhich.c
 app/wqrs.c
@@ -345,6 +349,7 @@
 doc/wag-src/wfdb-config.1
 doc/wag-src/wfdbdesc.1
 doc/wag-src/wfdbf.3
+doc/wag-src/wfdbmap.1
 doc/wag-src/wfdbtime.1
 doc/wag-src/wfdbwhich.1
 doc/wag-src/wqrs.1
@@ -575,12 +580,6 @@
 wave/xview-patches
 wave/xvwave.c
 wave/xvwave.h
-wfdbmap
-wfdbmap/Makefile
-wfdbmap/map-record
-wfdbmap/README
-wfdbmap/signal-colors.h
-wfdbmap/wfdbmap.c
 wfdb.spec
 xml
 xml/annxml.c
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/NEWS wfdb-10.5.10/NEWS
--- wfdb-10.5.9/NEWS	2011-09-10 15:06:37.000000000 -0400
+++ wfdb-10.5.10/NEWS	2011-11-16 14:55:48.573806584 -0500
@@ -1,3 +1,29 @@
+10.5.10 (15 November 2011):
+	The WFDB library function isigopen(), in lib/signal.c, searches each
+	component of the WFDB path for the signal file(s) named in the
+	associated header file, until a match is found.  Since signal files are
+	usually located in the same directories as header files, they can be
+	located most quickly by looking first in those directories.  Thanks to
+	David Brooks for suggesting this optimization and for a sample
+	implementation.
+
+	Attempts to set the default size for HTTP range requests (using the
+	environment variable WFDB_PAGESIZE) were ignored in previous versions
+        of the WFDB library when compiled with libcurl.  Thanks again to David
+        for noting this limitation, which has been eliminated in this release
+	by a change in www_init() (in lib/wfdbio.c).
+
+	'wfdbmap', which has been available in its own directory since release
+ 	10.5.6, is a now a standard application (app/wfdbmap.c).  'wfdbmap' is
+	used by the PhysioBank ATM to produce compact synoptic maps of WFDB-
+	compatible records.   Previous versions of 'wfdbmap' were unable to map
+	multi-segment records unless all segment headers were local;  this
+	limitation has been removed in this release.
+
+	This release also includes 'wfdbsignals' (app/wfdbsignals.c), used by
+	the PhysioBank ATM to list the signals in a WFDB record.  'wfdbsignals'
+	is  a stripped-down version of 'wfdbdesc'.
+
 10.5.9 (10 September 2011):
         When an application passes an array containing WFDB_INVALID_SAMPLE
         values to putvec(), the function translates these into the
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/wfdbmap/map-record wfdb-10.5.10/wfdbmap/map-record
--- wfdb-10.5.9/wfdbmap/map-record	2010-07-30 15:37:34.000000000 -0400
+++ wfdb-10.5.10/wfdbmap/map-record	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-#! /bin/bash
-
-# make a map of a WFDB record
-
-RL=$1
-RS=`basename $RL`
-shift
-
-wfdbmap -r $RL $* >$RS.script
-bash $RS.script >$RS.plt 2>/dev/null
-lwcat -strip -eps $RS.plt >$RS.ps
-convert -density 150 $RS.ps $RS.png
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/wfdbmap/README wfdb-10.5.10/wfdbmap/README
--- wfdb-10.5.9/wfdbmap/README	2010-11-04 10:28:34.000000000 -0400
+++ wfdb-10.5.10/wfdbmap/README	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-file: README		G. Moody	30 July 2010
-
-Software for creating 'maps' of PhysioBank records
-
-To build and install the software in this directory, first install the
-WFDB and plt software packages from PhysioNet, ImageMagick (from
-www.imagemagick.org), then return to this directory and type 'make'.
-
-This directory contains 'wfdbmap', a program that reads a WFDB record,
-optionally including one or more associated annotation files, and generates a
-script containing embedded data.  When the script is run, it creates (using
-'plt' and 'lwcat', from the plt package) a PostScript-format 'map' of the WFDB
-record and its annotations.  The maps displayed by the PhysioBank ATM are
-created in this way.
-
-Also in this directory is 'map-record', a shell script that illustrates how
-'wfdbmap' and (indirectly) 'plt are used to create a map, and how to convert
-the PostScript map into a PNG-format map (using 'convert' from ImageMagick).
-For example, to make a map of mitdb/200 and its associated 'atr' annotations,
-run the command:
-    map-record mitdb/200 -a atr
-The outputs of this command are 200.ps and 200.png.  If other annotation files
-are available, their annotator names can be given as additional command-line
-arguments:
-    map-record RECORD -a ANN1 ANN2 ANN3 ...
-
-*** A MAJOR LIMITATION of this version of wfdbmap is that it cannot properly
-map segments of a variable-layout multisegment record unless all of the
-.hea files for that record are local (i.e., they can't be retrieved from a
-web server as needed).  For the ATM, this is not a limitation at all, since
-the ATM is mapping local records on physionet.org.  For general use, it's
-a serious limitation, since variable-layout multisegment records are often
-the records for which a map would be most useful.
-
-The symptoms of this problem are a warning message of the form:
-    wfdbmap: can't open http://physionet.org/physiobank/database/...
-and an output map that shows all signals as missing. (The annotations are
-mapped properly, however.)
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/wfdbmap/signal-colors.h wfdb-10.5.10/wfdbmap/signal-colors.h
--- wfdb-10.5.9/wfdbmap/signal-colors.h	2009-04-09 16:44:18.000000000 -0400
+++ wfdb-10.5.10/wfdbmap/signal-colors.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,311 +0,0 @@
-struct sigcolor {
-    char *color;
-    char *class;
-    char *name;
-} ctab[] = {
-"red", "ECG", "Abdomen_1",
-"red", "ECG", "Abdomen_2",
-"red", "ECG", "Abdomen_3",
-"red", "ECG", "Abdomen_4",
-"green", "Resp", "Abdomen   [ABMV]",
-"green", "Resp", "ABDO RES",
-"blue", "BP", "ABP",
-"blue", "BP", "ABP_1/2",
-"blue", "BP", "ABP_2/2",
-"blue", "BP", "ABPDias",
-"blue", "BP", "ABPMean",
-"blue", "BP", "ABPSys",
-"blue", "BP", "AOBP",
-"blue", "BP", "AOBP_1/2",
-"blue", "BP", "AOBP_2/2",
-"blue", "BP", "AOBP Dias",
-"blue", "BP", "AOBP Mean",
-"blue", "BP", "AOBP Sys",
-"blue", "BP", "NBP_1/2",
-"blue", "BP", "NBP_2/2",
-"blue", "BP", "NBP",
-"blue", "BP", "NBPDias",
-"blue", "BP", "NBPMean",
-"blue", "BP", "NBPSys",
-"blue", "BP", "ABP Dias",
-"blue", "BP", "ABP Mean",
-"blue", "BP", "ABP Sys",
-"blue", "BP", "NBP Dias",
-"blue", "BP", "NBP Mean",
-"blue", "BP", "NBP Sys",
-"blue", "BP", "ABP ",
-"red", "ECG", "A-I",
-"green", "Resp", "AIRFLOW",
-"blue", "BP", "ART",
-"blue", "BP", "ART_1/2",
-"blue", "BP", "ART Dias",
-"blue", "BP", "ART Mean",
-"blue", "BP", "ART Sys",
-"blue", "BP", "ART ",
-"blue", "BP", "ART 1",
-"blue", "BP", "ART1 ",
-"blue", "BP", "ART^M                 ",
-"red", "ECG", "A-S",
-"red", "ECG", "avf",
-"red", "ECG", "aVF",
-"red", "ECG", "AVF",
-"red", "ECG", "AVF+",
-"red", "ECG", "avl",
-"red", "ECG", "aVL",
-"red", "ECG", "AVL",
-"red", "ECG", "avr",
-"red", "ECG", "aVR",
-"red", "ECG", "AVR",
-"darkgreen", "Temp", "BLOODT",
-"darkgreen", "Temp", "BLOODT_1/3",
-"darkgreen", "Temp", "BLOODT_2/3",
-"darkgreen", "Temp", "BLOODT_3/3",
-"blue", "BP", "BP",
-"blue", "BP", " BP",
-"pink", "noise", "BW noise, signal 0",
-"pink", "noise", "BW noise, signal 1",
-"darkred", "CO", "CO",
-"darkred", "CO", "CO_1/2",
-"darkred", "CO", "CO_1/3",
-"darkred", "CO", "CO_2/2",
-"darkred", "CO", "CO_2/3",
-"darkred", "CO", "CO_3/3",
-"purple", "CO2", "C02",
-"blue", "BP", "CVP",
-"blue", "BP", "CVP_1/2",
-"blue", "BP", "CVP_1/3",
-"blue", "BP", "CVP_2/2",
-"blue", "BP", "CVP_2/3",
-"blue", "BP", "CVP_3/3",
-"red", "ECG", "CC5",
-"red", "ECG", "chan 1",
-"red", "ECG", "chan 2",
-"red", "ECG", "chan 3",
-"red", "ECG", "CM2",
-"red", "ECG", "CM4",
-"red", "ECG", "CM5",
-"purple", "CO2", "Co2",
-"purple", "CO2", "CO2",
-"purple", "CO2", "CO2^M ",
-"red", "ECG", "CS12",
-"red", "ECG", "CS34",
-"red", "ECG", "CS56",
-"red", "ECG", "CS78",
-"red", "ECG", "CS90",
-"blue", "BP", "CVP",
-"blue", "BP", "CVP 3",
-"red", "ECG", "D3",
-"red", "ECG", "D4",
-"red", "ECG", "ECG",
-"red", "ECG", " ECG",
-"red", "ECG", "ECG0",
-"red", "ECG", "ECG1",
-"red", "ECG", "ECG 1",
-"red", "ECG", "ECG 2",
-"red", "ECG", "ECG 3",
-"red", "ECG", "ECG AVF",
-"red", "ECG", "ECG       [ECG1]",
-"red", "ECG", "ECG F",
-"red", "ECG", "ECG I",
-"red", "ECG", "ECG II",
-"red", "ECG", "ECG III",
-"red", "ECG", "ECG lead 1",
-"red", "ECG", "ECG lead 2",
-"red", "ECG", "ECG lead 3",
-"red", "ECG", "ECG Lead AVF",
-"red", "ECG", "ECG lead AVL",
-"red", "ECG", "ECG lead I",
-"red", "ECG", "ECG Lead I",
-"red", "ECG", "ECG lead II",
-"red", "ECG", "ECG lead II ",
-"red", "ECG", "ECG LeadII",
-"red", "ECG", "ECG Lead II",
-"red", "ECG", "ECG lead III",
-"red", "ECG", "ECG Lead III",
-"red", "ECG", "ECG lead V",
-"red", "ECG", "ECG Lead V",
-"red", "ECG", "ECG Lead V ",
-"red", "ECG", "ECG Lead V3",
-"red", "ECG", "ECG Lead V4",
-"red", "ECG", "ECG lead V5",
-"red", "ECG", "ECG Lead V5",
-"red", "ECG", "ECG lead V6",
-"red", "ECG", "ECG MCL",
-"red", "ECG", "ECG signal 0",
-"red", "ECG", "ECG signal 1",
-"red", "ECG", "ECG V",
-"red", "ECG", "ECG V3",
-"red", "ECG", "ECG V Lead",
-"grey", "Annot", "EDF Annotations",
-"yellow", "EEG", "EEG",
-"yellow", "EEG", "EEG C3-A2 [C3A2]",
-"yellow", "EEG", "EEG (C3-O1)",
-"yellow", "EEG", "EEG (C4-A1)",
-"yellow", "EEG", "EEG C4-A1 [C4A1]",
-"yellow", "EEG", "EEG Fpz-Cz",
-"yellow", "EEG", "EEG (O2-A1)",
-"yellow", "EEG", "EEG Pz-Oz",
-"yellow", "EEG", "EEG(sec)",
-"orange", "EMG", "EMG",
-"orange", "EMG", "EMG-Chin  [EMYG]",
-"orange", "EMG", "EMG submental",
-"orange", "EMG", "EMG Submental",
-"pink", "noise", "EM noise, signal 0",
-"pink", "noise", "EM noise, signal 1",
-"lightblue", "EOG", "EOG",
-"lightblue", "EOG", "EOG E1-A1 [EOGL]",
-"lightblue", "EOG", "EOG E2-A1 [EOGR]",
-"lightblue", "EOG", "EOG horizontal",
-"lightblue", "EOG", "EOG(L)",
-"lightblue", "EOG", "EOG(R)",
-"lightblue", "EOG", "EOG (right)",
-"red", "ECG", "E-S",
-"grey", "Annot", "Event marker",
-"green", "Resp", "Flow      [AFLO]",
-"grey", "Annot", "Hypnogram",
-"red", "ECG", "i",
-"red", "ECG", "I",
-"red", "ECG", "I ",
-"red", "ECG", "I+",
-"blue", "BP", "ICP",
-"grey", "Annot", "ID+Sync+Error",
-"red", "ECG", "ii",
-"red", "ECG", "II",
-"red", "ECG", "II ",
-"red", "ECG", "II+",
-"red", "ECG", "iii",
-"red", "ECG", "III",
-"red", "ECG", "III ",
-"red", "ECG", "III+",
-"blue", "BP", "LAP",
-"red", "ECG", "lead I",
-"red", "ECG", "lead II",
-"red", "ECG", "lead V",
-"pink", "noise", "MA noise, signal 0",
-"pink", "noise", "MA noise, signal 1",
-"red", "ECG", "MCL1",
-"red", "ECG", "MCL1 ",
-"red", "ECG", "MCL1+",
-"red", "ECG", "ML2",
-"red", "ECG", "ML5",
-"red", "ECG", "MLI",
-"red", "ECG", "MLII",
-"red", "ECG", "MLIII",
-"red", "ECG", "mod.V1",
-"red", "ECG", "MV2",
-"red", "ECG", "MV2   ",
-"blue", "BP", "P1",
-"blue", "BP", "P1 Dias",
-"blue", "BP", "P1 Mean",
-"blue", "BP", "P1 Sys",
-"blue", "BP", "PA",
-"blue", "BP", "PAP",
-"blue", "BP", "PAP_1/2",
-"blue", "BP", "PAP_2/2",
-"blue", "BP", "PAP ",
-"blue", "BP", "PAP Dias",
-"blue", "BP", "PAP Mean",
-"blue", "BP", "PAP Sys",
-"blue", "BP", "PAP 2",
-"blue", "BP", "PAWP",
-"blue", "BP", "PAWP_1/2",
-"blue", "BP", "PAWP_1/3",
-"blue", "BP", "PAWP_2/2",
-"blue", "BP", "PAWP_2/3",
-"blue", "BP", "PAWP_3/3",
-"darkblue", "PLETH", "PLETH",
-"darkblue", "PLETH", "PLETH ",
-"grey", "Pos", "Position",
-"orangered", "HR", "HR",
-"orangered", "HR", "HR_1/2",
-"orangered", "HR", "HR_1/3",
-"orangered", "HR", "HR_2/2",
-"orangered", "HR", "HR_2/3",
-"orangered", "HR", "HR_3/3",
-"orangered", "HR", "PR",
-"blue", "BP", "Pressure",
-"blue", "BP", "Pressure ",
-"blue", "BP", "Pressure1",
-"blue", "BP", "Pressure 1",
-"blue", "BP", "Pressure 2",
-"blue", "BP", "Pressure 3",
-"blue", "BP", "Pressure 4",
-"orangered", "HR", "Pulse",
-"orangered", "HR", "PULSE",
-"orangered", "HR", "PULSE_1/2",
-"orangered", "HR", "PULSE_1/3",
-"orangered", "HR", "PULSE_2/2",
-"orangered", "HR", "PULSE_2/3",
-"orangered", "HR", "PULSE_3/3",
-"orangered", "HR", "PVC Rate per Minute",
-"orangered", "HR", "PVC Rate per Minute_1/2",
-"orangered", "HR", "PVC Rate per Minute_1/3",
-"orangered", "HR", "PVC Rate per Minute_2/3",
-"orangered", "HR", "PVC Rate per Minute_3/3",
-"blue", "BP", "RAP",
-"green", "Resp", "RESP",
-"green", "Resp", "RESP_1/2",
-"green", "Resp", "RESP_1/3",
-"green", "Resp", "RESP_2/2",
-"green", "Resp", "RESP_2/3",
-"green", "Resp", "RESP_3/3",
-"green", "Resp", " RESP",
-"green", "Resp", "RESP ",
-"green", "Resp", "Resp A",
-"green", "Resp", "Resp (abdomen)",
-"green", "Resp", "Resp (abdominal)",
-"green", "Resp", "Resp C",
-"green", "Resp", "Resp (chest)",
-"green", "Resp", "Resp Imp",
-"green", "Resp", "Resp. Imp.",
-"green", "Resp", "Resp.Imp.",
-"green", "Resp", "RESP IMP",
-"green", "Resp", "Resp Inp.",
-"green", "Resp", "Resp N",
-"green", "Resp", "Resp (nasal)",
-"green", "Resp", "Resp oro-nasal",
-"green", "Resp", "Resp (sum)",
-"darkred", "O2", "SaO2",
-"darkred", "O2", "SaO2      [OSAT]",
-"darkred", "O2", "SO2",
-"grey", "Sound", "Sound",
-"darkred", "O2", "SpO2",
-"darkred", "O2", "SpO2_1/2",
-"darkred", "O2", "SpO2_1/3",
-"darkred", "O2", "SpO2_2/2",
-"darkred", "O2", "SpO2_2/3",
-"darkred", "O2", "SpO2_3/3",
-"green", "Resp", "Sum",
-"magenta", "SV", "SV",
-"darkgreen", "Temp", "Temp body",
-"green", "Resp", "Thorax_1",
-"green", "Resp", "Thorax_2",
-"green", "Resp", "Thorax    [CHMV]",
-"green", "Resp", "THOR RES",
-"blue", "BP", "UAP",
-"blue", "BP", "UAP Dias",
-"blue", "BP", "UAP Mean",
-"blue", "BP", "UAP Sys",
-"red", "ECG", "V",
-"red", "ECG", "V ",
-"red", "ECG", "V+",
-"red", "ECG", "v1",
-"red", "ECG", "V1",
-"red", "ECG", "V1-V2",
-"red", "ECG", "v2",
-"red", "ECG", "V2",
-"red", "ECG", "V2-V3",
-"red", "ECG", "v3",
-"red", "ECG", "V3",
-"red", "ECG", "v4",
-"red", "ECG", "V4",
-"red", "ECG", "V4-V5",
-"red", "ECG", "v5",
-"red", "ECG", "V5",
-"red", "ECG", "v6",
-"red", "ECG", "V6",
-"red", "ECG", "vx",
-"red", "ECG", "vy",
-"red", "ECG", "vz",
-NULL,   NULL,   NULL
-};
diff -Naur --exclude Makefile --exclude info wfdb-10.5.9/wfdbmap/wfdbmap.c wfdb-10.5.10/wfdbmap/wfdbmap.c
--- wfdb-10.5.9/wfdbmap/wfdbmap.c	2009-03-30 02:22:56.000000000 -0400
+++ wfdb-10.5.10/wfdbmap/wfdbmap.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,469 +0,0 @@
-/* file: wfdbmap.c	G. Moody       	22 March 2009
-			Last revised:	30 March 2009
-
--------------------------------------------------------------------------------
-wfdbmap: generates a 'plt' script to make a PostScript map of a WFDB record
-Copyright (C) 2009 George B. Moody
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; either version 2 of the License, or (at your option) any later
-version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place - Suite 330, Boston, MA 02111-1307, USA.
-
-You may contact the author by e-mail (george@mit.edu) or postal mail
-(MIT Room E25-505A, Cambridge, MA 02139 USA).  For updates to this software,
-please visit PhysioNet (http://www.physionet.org/).
-_______________________________________________________________________________
-
-*/
-
-#include <stdio.h>
-#include <wfdb/wfdb.h>
-#include <wfdb/ecgcodes.h>
-#include <wfdb/ecgmap.h>
-
-char *pname;
-WFDB_Anninfo *ai = NULL;
-WFDB_Siginfo *si = NULL;
-int mflag = 0;
-int spm;
-
-main(argc, argv)
-int argc;
-char *argv[];
-{
-    char *record = NULL, *prog_name();
-    int i, j, length, **map = NULL, nann = 0, nsig;
-    void help();
-    void map_sig(char *record, WFDB_Siginfo *si, int nsig,int **map,int length);
-    void map_ann(char *record, WFDB_Anninfo *ai, int nann,int **map,int length);
-    void write_map(int **map, int nsig, int nann, int length);
-    void write_script(int **map, int nsig, int nann, int length);
-
-    pname = prog_name(argv[0]);
-
-    /* Interpret command-line options. */
-    for (i = 1; i < argc; i++) {
-	if (*argv[i] == '-') switch (*(argv[i]+1)) {
-	  case 'a':	/* annotators follow */
-	    if (++i >= argc) {
-		(void)fprintf(stderr, "%s: annotators must follow -a\n",
-			      pname);
-		exit(1);
-	    }
-	    /* how may annotators are there? */
-	    for (j = i; j < argc && *argv[j] != '-'; j++)
-		;
-	    nann = j - i;
-	    /* allocate *ai and initialize it */
-	    if (nann > 0) {
-		if ((ai = malloc(nann * sizeof(WFDB_Anninfo))) == NULL) {
-		    fprintf(stderr, "%s: insufficient memory\n", pname);
-		    exit(2);
-		}
-		for (j = 0; j < nann; j++) {
-		    ai[j].name = argv[i++];
-		    ai[j].stat = WFDB_READ;
-		}
-	    }
-	    i--;
-	    break;
-	  case 'h':	/* print usage summary and quit */
-	    help();
-	    exit(0);
-	    break;
-          case 'm':     /* print map only */
-	    mflag = 1;
-	    break;
-	  case 'r':	/* input record name follows */
-	    if (++i >= argc) {
-		(void)fprintf(stderr,
-			      "%s: input record name must follow -r\n",
-			      pname);
-		exit(1);
-	    }
-	    record = argv[i];
-	    break;
-	  default:
-	    (void)fprintf(stderr, "%s: unrecognized option %s\n",
-			  pname, argv[i]);
-	    exit(1);
-	}
-	else {
-	    (void)fprintf(stderr, "%s: unrecognized argument %s\n",
-			  pname, argv[i]);
-	    exit(1);
-	}
-    }
-    if (record == NULL) {
-	help();
-	exit(1);
-    }
-
-    nsig = isigopen(record, NULL, 0);
-    if (nsig > 0) {
-	if ((si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) {
-	    fprintf(stderr, "%s: insufficient memory\n", pname);
-	    if (ai) { wfdbquit(); free(ai); }
-	    exit(2);
-	}
-	if ((nsig = isigopen(record, si, nsig)) < 0)
-	    nsig = 0;
-    }
-    spm = strtim("60");
-    length = (strtim("e") + (spm-1))/spm;  /* number of minutes in record */
-
-    if (length < 1 && nsig > 0) {
-        /* calculate the length of the record from the signal file size */
-        char *p;
-        double fs = 0;
-	FILE *ifile;
-	long bpm;
-
-        for (i = 0; i < nsig && si[i].group == 0; i++)
-	  switch (si[i].fmt) {
-	  case 8:
-	  case 80:  fs += si[i].spf; break;
-	  case 310:
-	  case 311: fs += 1.33333333*si[i].spf; break;
-	  case 212: fs += 1.5*si[i].spf; break;
-	  default:  fs += 2*si[i].spf; break;
-	  }
-	bpm = fs * spm + 0.5;  /* bytes per minute */
-	p = wfdbfile(si[i].fname, NULL);
-	ifile = fopen(p, "r");
-	fseek(ifile, 0L, SEEK_END);
-	length = ftell(ifile)/bpm;
-	fclose(ifile);
-    }
-
-    if (length < 1) {	/* try to get length from annotation file(s) */
-        int alen;
-        WFDB_Annotation annot;
-	WFDB_Time t;
-
-        for (i = 0; i < nann; i++) {
-	    if (annopen(record, &ai[i], 1) < 0) continue;
-	    while (getann(0, &annot) >= 0)
-	        t = annot.time;
-	    alen = (t + (spm-1))/spm;
-	    if (alen > length) length = alen;
-	}
-    }
-
-    if (length > 60000) /* 1000 hours > 41 days */
-        length = 60000;		/* truncate extremely long records */
-
-    if (length < 1) {
-	fprintf(stderr, "%s: can't map record %s (length unspecified)\n",
-		pname, record);
-	exit(1);
-    }
-
-    if ((map = malloc((nsig + 4*nann) * sizeof(int *))) == NULL) {
-	fprintf(stderr, "%s: insufficient memory\n", pname);
-	wfdbquit();
-	if (ai) free(ai);
-	if (si) free(si);
-	exit(2);
-    }
-    for (i = 0; i < nsig + 4*nann; i++)
-	if ((map[i] = calloc(length, sizeof(int))) == NULL) {
-	    fprintf(stderr, "%s: insufficient memory\n", pname);
-	    while (--i > 0)
-		if (map[i]) free(map[i]);
-	    free(map);
-	    wfdbquit();
-	    if (ai) free(ai);
-	    if (si) free(si);
-	    exit(2);
-	}
-
-    if (nsig > 0) map_sig(record, si, nsig, map, length);
-    if (nann > 0) map_ann(record, ai, nann, &map[nsig], length);
-
-    if (mflag) {
-	printf("T");
-	for (i = 0; i < nsig; i++)
-	    printf("\t%s", si[i].desc);
-	for (i = 0; i < nann; i++)
-	    printf("\t%s\tQRS\tEctopic\tVE", ai[i].name);
-	printf("\n");
-	write_map(map, nsig, nann, length);
-    }
-    else
-	write_script(map, nsig, nann, length);
-	
-    for (i = 0; i < nsig + 4*nann; i++)
-	free(map[i]);
-    free(map);
-    wfdbquit();
-    if (ai) free(ai);
-    if (si) free(si);
-
-    exit(0);
-}
-
-void map_sig(char *record, WFDB_Siginfo *si, int nsig, int **map, int length)
-{
-    if (si[0].nsamp == strtim("e") || si[0].nsamp != 0) {
-	/* fixed-layout record */
-        int i, t;
-	for (i = 0; i < nsig; i++)
-	    for (t = 0; t < length; t++)
-		map[i][t] = 1;
-    }
-    else {	/* variable-layout record */
-	char buf[256], *d, *p, *q, *r, *hfname, *shfname;
-	long m, m0, mf, spm = strtim("60"), t = 0, tf;
-	FILE *ifile, *sfile;
-
-	p = wfdbfile("hea", record);
-	hfname = calloc(strlen(p) + 1, 1);
-	strcpy(hfname, p);
-	if ((ifile = fopen(hfname, "r")) == NULL) {
-	    fprintf(stderr, "%s: can't open %s\n", pname, hfname);
-	    free(hfname);
-	    return;
-	}
-	for (d = p + strlen(p); d > p; d--)
-	    if (*(d-1) == '/') {
-		*d = '\0';
-		break;
-	    }
-	shfname = calloc(strlen(hfname) + 16, 1);
-	strcpy(shfname, p);
-	d = shfname + strlen(shfname);   /* d points to first char after '/' */
-	fgets(buf, sizeof(buf), ifile);  /* read and ignore first two lines */
-	fgets(buf, sizeof(buf), ifile);
-
-	m0 = 0;
-	while (fgets(buf, sizeof(buf), ifile)) {/* read a segment descriptor */ 
-	    char *tp;
-
-	    if (buf[0] == '~') {  /* segment is null (all signals off) */
-		t += atol(buf+2);
-		m0 = t/spm;
-		continue;
-	    }
-	    for (tp = buf+1; *tp != ' '; tp++)
-		; 
-	    *tp = '\0';
-	    tf = t + atol(tp+1);
-	    if ((mf = tf/spm) > length) mf = length;
-	    sprintf(d, "%s.hea", buf);
-	    if (sfile = fopen(shfname, "r")) {/* open the segment header file */
-		char sbuf[256];
-		int i;
-
-		fgets(sbuf, sizeof(sbuf), sfile);/* read & ignore first line */
-      
-		while ((p = fgets(sbuf, sizeof(sbuf), sfile)) && *sbuf != '#') {
-		    /* signal description line */
-		    for (q = sbuf, i = 0; *q; q++)
-			if (*q == ' ' && ++i == 8) break;
-		    q++;
-		    *(q + strlen(q) - 2) = '\0';
-		    for (i = 0; i < nsig; i++)
-			if (strcmp(si[i].desc, q) == 0)
-			    for (m = m0; m < mf; m++)
-				map[i][m] = 1;
-		}
-		fclose(sfile);
-		t = tf;
-		m0 = t/spm;
-	    }
-	}
-	fclose(ifile);
-	free(shfname);
-	free(hfname);
-    }
-}
-
-int *namax;
-
-void map_ann(char *record, WFDB_Anninfo *ai, int nann, int **map, int length)
-{
-    int i;
-
-    namax = malloc(nann * sizeof(int));
-    wfdbquiet();   /* suppress warnings if an annotator can't be opened */
-    for (i = 0; i < nann; i++) {
-	char tstring[10];
-	int minutes, *na, *nq, *ne, *nv;
-	WFDB_Annotation annot;
-	WFDB_Time end_of_epoch;
-
-	na = &map[4*i][0];
-	namax[i] = 1;
-
-	/* Open the annotators one at a time, and do not quit if any fail
-	   to open. */
-	if (annopen(record, &ai[i], 1) < 0) continue;
-	minutes = end_of_epoch = 0;
-	iannsettime(1L);
-	while (getann(0, &annot) >= 0) {
-	    if (annot.time > end_of_epoch) {
-	        if (*na > namax[i]) namax[i] = *na;
-		minutes = annot.time/spm;
-		na = &map[4*i][minutes];
-		nq = &map[4*i + 1][minutes];
-		ne = &map[4*i + 2][minutes];
-		nv = &map[4*i + 3][minutes];
-		if (++minutes > length)
-		    break;	/* stop at the end of the record */
-		sprintf(tstring, "%d", 60*minutes);
-		end_of_epoch = strtim(tstring);
-	    }
-	    switch (annot.anntyp) {
-	    case PVC:
-	    case FUSION:
-	    case VESC:
-	    case RONT:
-	    case FLWAV:	(*nv)++;	/* fall through, no break! */
-	    case APC:
-	    case ABERR:
-	    case NPC:
-	    case SVPB:
-	    case NESC:
-	    case AESC:
-	    case SVESC:	(*ne)++;	/* fall through, no break! */
-	    case NORMAL:
-	    case LBBB:
-	    case RBBB:
-	    case PACE:
-	    case UNKNOWN:
-	    case BBB:
-	    case LEARN:
-	    case PFUS:	(*nq)++;	/* fall through, no break! */
-	    default:	(*na)++; break;
-	    }
-	}
-	if (*na > namax[i]) namax[i] = *na;
-    }
-    return;
-}
-
-void write_map(int **map, int nsig, int nann, int length)
-{
-    int i, imax = nsig + 4*nann - 1, t;
-
-    for (t = 0; t < length; t++) {
-	if (mflag == 0) printf("%d\t0\t", t); /* x0, y0 for histogram plots */
-	printf("%d\t", t+1);
-	for (i = 0; i < imax; i++)
-	    printf("%d\t", map[i][t]);
-	printf("%d\n", map[i][t]);
-    }
-}
-
-#include "signal-colors.h"
-
-char *color(char *type)
-{
-    int i;
-
-    for (i = 0; ctab[i].name != NULL; i++)
-	if (strcmp(type, ctab[i].name) == 0) return (ctab[i].color);
-    return ("grey");
-}
-
-void write_script(int **map, int nsig, int nann, int length)
-{
-  char *p, tstring[2][30];
-    double ylow, ymax;
-    int i, j;
-    WFDB_Time tf = strtim("e");
-
-    strcpy(tstring[0], timstr(0));
-    for (p = tstring[0]; *p == ' '; p++)
-        ;
-    if (tf) strcpy(tstring[1], timstr(-tf));
-    else sprintf(tstring[1], "%d:%02d:00", length/60, length%60);
-
-    ymax = 2*(nsig + 2*nann + 1);
-    ylow = 0.01 * ymax;
-
-    printf("#! /bin/sh\n"
-	   "cat >map.txt <<EOF\n");
-    write_map(map, nsig, nann, length);
-    printf("EOF\n\n");
-
-    printf("MAP=map.txt\n"
-	   "FDEF=\"-sf l Fh,P8\"\n"
-	   "LDEF=\"-setxy -l %g 0 RB\"\n"
-	   "WDEF=\"-W .048 .1 .982 1\"\n"
-	   "XDEF=\"-X 0 %d\"\n"
-	   "OPT=\"$FDEF $XDEF $WDEF $LDEF\"\n",
-	   -0.005*length, length);
-    
-    printf("lwplt $WDEF $XDEF -Y 0 %g -stxy -sf l Fh-b,P12", ymax);
-    printf(" -l 0 %g LT \"%s\"", ylow, p);
-    printf(" -l %g %g CT \"time\"", 0.5*length, ylow);
-    printf(" -l %d %g RT \"%s\"\n\n", length, ylow, tstring[1]);
-
-    for (i = 0; i < nann; i++) {
-	j = nsig + i;
-	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT %s\n",
-	       j+3*i+3, "grey", 0.5*namax[i]*(2*(j+i+2) - ymax),
-	       0.5*namax[i]*2*(j+i+2), ai[i].name);
-	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT %s\n",
-	       j+3*i+4, "black", 0.5*namax[i]*(2*(j+i+2) - ymax),
-	       0.5*namax[i]*2*(j+i+2), ai[i].name);
-	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT %s\n",
-	       j+3*i+5, "blue", 0.5*namax[i]*(2*(j+i+2) - ymax),
-	       0.5*namax[i]*2*(j+i+2), ai[i].name);
-	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT %s\n",
-	       j+3*i+6, "red", 0.5*namax[i]*(2*(j+i+2) - ymax),
-	       0.5*namax[i]*2*(j+i+2), ai[i].name);
-    }
-
-    for (i = 0; i < nsig; i++)
-	printf("lwplt $MAP -p\"0,1,2,%dh(C%s)\" -Y %g %g $OPT \"%s\"\n",
-	       i+3, color(si[i].desc), 2.*(i+1) - ymax,
-	       2.*(i+1), si[i].desc);
-}
-
-char *prog_name(s)
-char *s;
-{
-    char *p = s + strlen(s);
-
-#ifdef MSDOS
-    while (p >= s && *p != '\\' && *p != ':') {
-	if (*p == '.')
-	    *p = '\0';		/* strip off extension */
-	if ('A' <= *p && *p <= 'Z')
-	    *p += 'a' - 'A';	/* convert to lower case */
-	p--;
-    }
-#else
-    while (p >= s && *p != '/')
-	p--;
-#endif
-    return (p+1);
-}
-
-static char *help_strings[] = {
- "usage: %s -r RECORD -a ANNOTATOR [OPTIONS ...]\n",
- "where RECORD and ANNOTATOR specify the input, and OPTIONS may include:",
- " -h       print this usage summary",
-NULL
-};
-
-void help()
-{
-    int i;
-
-    (void)fprintf(stderr, help_strings[0], pname);
-    for (i = 1; help_strings[i] != NULL; i++)
-	(void)fprintf(stderr, "%s\n", help_strings[i]);
-}
