/* Print an EBS file on a PostScript printer Copyright (C) 1993/94 M. Prosch, Institut fuer Physiologie und Biokybernetik (IPB), Universitaet Erlangen, Deutschland Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and related publications and that both that copyright notice and this permission notice appear in supporting documentation. The authors make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. Send your comments, suggestions or bug reports to ftpebs@uni-erlangen.de Or mail to Institut fuer Physiologie und Biokybernetik Markus Prosch Universitaetsstrasse 17 D-91054 Erlangen Germany $Id: ebsprint.c,v 1.4 1994/03/17 11:49:33 msprosch Exp $ */ #include #include #include #include #include #include #include #include #ifndef MSDOS #include #endif #include "ebs.h" #include "ebshead.h" /* for pre-ANSI-versions of stdio.h */ #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CURRENT #define SEEK_CURRENT 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef PI #define PI 3.14159265358979323846 #endif #ifdef MSDOS #include "setstack.c" #endif /* Y Resolution in unit/mm, default 25/mm */ #define YUNIT 25 #define MMTOXRES(x) ((int)((double)(x)/25.4*dpi)) #define MMTOPOINTS(v) ((int) ((double) (v)/25.4*72.0)) #ifndef PI #define PI 3.14159265358979323846 #endif char copyright[]= "Print an EBS file on a PostScript printer.\n" "Copyright (C) 1993/94 M. Prosch, M. Kuhn, Institut fuer Physiologie und\n" " Biokybernetik (IPB), Universitaet Erlangen, Deutschland\n\n" "Permission to use, copy, modify, distribute, and sell this software\n" "and its documentation for any purpose is hereby granted without fee,\n" "provided that the above copyright notice appear in all copies and\n" "related publications and that both that copyright notice and this\n" "permission notice appear in supporting documentation. The authors make\n" "no representations about the suitability of this software for any\n" "purpose. It is provided \"as is\" without express or implied warranty.\n\n" "Send your comments, suggestions or bug reports to\n" " ftpebs@uni-erlangen.de\n\n" "Or mail to\n" " Institut fuer Physiologie und Biokybernetik\n" " Markus Prosch\n" " Universitaetsstrasse 17\n" " D-91054 Erlangen\n" " Germany\n\n"; char version[] = "EBSprint V0.9 "__DATE__"\n" "(C) 1993/94 Markus Prosch, IPB, Erlangen"; char version_short[] = "EBSprint V0.9, \\251 1994 M. Prosch, IPB, Erlangen"; char version_short_asc[]= "EBSprint V0.9, (C) 1994 M. Prosch, IPB, Erlangen"; char usage[] = "%s\n\n" "usage: %s [-p] [-a] [-t] [-r]\n" " [-x] [-y] [-z] [-i]\n" " \n" "\noptions:\n" "\t-c print out copyright notice\n" "\t-h print out this message\n" "\t-p select papersize (a4l, a4p, a3l, a3p), default a4l\n" "\t-a anonymize\n" "\t-t supress output of title page\n" "\t-r select resolution, default 72\n" "\t-x x scaling, default 30 (i.e 30mm/sec)\n" "\t-y y scaling, default 70uV,2000bins(i.e 70uV/cm, 2000bins/cm)\n" "\t-z print zero lines\n" "\t-i intervall, default 0,-1 (entire file)\n\n"; struct paper { char name [10]; /* lowercase */ int maxx, maxy; /* in mm */ int borderx, bordery; /* in mm */ int rotate; }; /* allowed papersizes */ struct paper paper []= { {"a4p", 210, 297, 10, 10, 0}, {"a4l", 297, 210, 10, 10, 1}, {"a3p", 297, 420, 10, 10, 0}, {"a3l", 420, 297, 10, 10, 1}, {"", 0, 0, 0, 0, 0} }; struct yscale { char unit [10]; float scale; }; int paperno= 1; /* a4l */ int anonymous= 0; double dpi= 72.0, dots_per_sec= -1; unsigned long start= 0, length= 0xffffffffL; /* number of samples */ int pages= 0; int page= 1; int *electrode= NULL, nelectrodes= 0; struct yscale *yscale=NULL; struct yscale *electrodescale=NULL; int nyscales=0; int mm_per_sec= 30; /* 30mm/sec */ enum timeformat {onlytime, onlydate, timeanddate}; #define DESCHEIGHT 12.0 #define TIMEHEIGHT 8.0 #define NORMALHEIGHT 12.0 #define BOLDHEIGHT 12.0 #define CHANNELHEIGHT 15.0 #define SMALLHEIGHT 9.0 char ps_procs []= "/Helvetica findfont\n" " dup length dict begin\n" " {1 index /FID ne {def} {pop pop} ifelse} forall\n" " /Encoding ISOLatin1Encoding def\n" " currentdict\n" "end\n" "/Helvetica-ISO exch definefont pop\n\n" "/Helvetica-Bold findfont\n" " dup length dict begin\n" " {1 index /FID ne {def} {pop pop} ifelse} forall\n" " /Encoding ISOLatin1Encoding def\n" " currentdict\n" "end\n" "/Helvetica-Bold-ISO exch definefont pop\n\n" "/Courier findfont\n" " dup length dict begin\n" " {1 index /FID ne {def} {pop pop} ifelse} forall\n" " /Encoding ISOLatin1Encoding 256 array copy def\n" " Encoding 8#200 /bullet put\n" " currentdict\n" "end\n" "/Courier-ISO exch definefont pop\n\n" "/indent {\n" " /xcur xleft cm 2 div add def\n" " xcur currentpoint exch pop moveto\n" "} def\n\n" "/extraindent {\n" " /xcur xleft cm 2 div add def\n" " xcur currentpoint exch pop moveto\n" " dup show stringwidth pop xcur add /xcur exch def\n" " xcur currentpoint exch pop moveto\n" "} def\n\n" "/noindent {\n" " /xcur xleft def\n" " xcur currentpoint exch pop moveto\n" "} def\n\n" "/nl {\n" " currentpoint height sub exch pop xcur exch moveto\n" "} def\n\n" "/p {\n" " currentpoint exch pop bottom gt {show nl} {pop} ifelse\n" "} def\n\n" "/bp {\n" " BoldFont setfont show\n" "} def\n\n" "/bnp1 {\n" " BoldFont setfont exch show NormalFont setfont show nl\n" "} def\n\n" "/tab 0 def\n" "/stab {\n" " BoldFont setfont\n" " /tab exch stringwidth pop currentpoint pop add def\n" "} def\n\n" "/bnp {\n" " /s2 exch def\n" " /s1 exch def\n" " BoldFont setfont s1 show NormalFont setfont\n" " tab currentpoint exch pop moveto s2 show\n" "} def\n\n" "/tr {\n" " /str exch def\n" " /x exch def\n" " /x str stringwidth pop x exch sub def\n" " x currentpoint exch pop moveto\n" " str show\n" "} def\n\n" "%% Draw curves\n" "/dc {\n" " /ary exch def\n" " /y exch def\n" " /x exch def\n" " newpath\n" " x y ary 0 get add moveto\n" " /x x 1 add def\n" " 1 1 ary length 1 sub\n" " {\n" " ary exch get y add x exch lineto\n" " /x x 1 add def\n" " } for\n" " 0 setgray\n" " stroke\n" "} def\n\n" "%% Draw curves\n" "/dc2 {\n" " /li exch def\n" " /ci exch def\n" " /y topy offset sub def\n" " /bla 10 string def\n" " 1 1 ci {\n" " /c exch def\n" " /x xmin def\n" " 1 1 li {\n" " /l exch def\n" " currentfile f readline pop /fs exch def\n" " newpath\n" " x fs 0 get 94 mul fs 1 get add y add moveto\n" " /x x 1 add def\n" " 2 2 fs length 1 sub {\n" " dup fs exch get 94 mul exch fs exch 1 add get add y add x exch lineto\n" " /x x 1 add def\n" " } for\n" " stroke\n" " /x x 1 sub def\n" " } for\n" " /y y hy sub def\n" " } for\n" "} def\n\n" "%% Show time\n" "/st {\n" " /str exch def\n" " /x exch def\n" " /ymax exch def\n" " /ymin exch def\n" " /len str stringwidth pop def\n" " /start x len 2 div sub def\n" " start tabul gt tabur start len add gt and\n" " {start ymax mmy add moveto str show /tabul start len cmx add add def} if\n" " newpath\n" " x ymin moveto\n" " x ymax lineto\n" " stroke\n" "} def\n\n" "%% Show channels\n" "/sc {\n" " /ary exch def\n" " /x2 exch def\n" " /x1 exch def\n" " /y topy def\n" " 0 1 ary length 1 sub\n" " 0.8 setgray\n" " [1 4] 0 setdash\n" " {\n" " /i exch def\n" " /y topy hy i mul sub def\n" " zerolines 1 eq {0 setgray newpath xmin y moveto xmax y lineto\n" " stroke 0.8 setgray} if\n" " x1 y moveto ary i get show\n" " x2 y moveto ary i get show\n" " } for\n" " [ ] 0 setdash\n" "} def\n\n" "%% Print top\n" "/pt {\n" " /str exch def\n" " /y exch def\n" " /x exch def\n" " x y moveto\n" " str show\n" "} def\n\n" "%% Print top center\n" "/ptc {\n" " /str exch def\n" " /y exch def\n" " /x exch def\n" " /x str stringwidth pop 2 div x exch sub def\n" " x y moveto\n" " str show\n" "} def\n\n" "%% Print top right\n" "/ptr {\n" " /str exch def\n" " /y exch def\n" " /x exch def\n" " /x str stringwidth pop x exch sub def\n" " x y moveto\n" " str show\n" "} def\n\n"; struct header { char *filename; int ebs_type; int number_of_electrodes; float sample_rate; int sample_rate_specified; int samples_per_channel; int samples_per_channel_specified; char **electrode_name; char **electrode_unit; float *electrode_scale; int *preferred_range_min; int *preferred_range_max; char null; char *pointer_to_samples; char *patientname; char *patientid; char *patientsex; char *patientbirthday; char *institution; char *recordingtime; char *recordingdate; time_t starttime; char *shortdescription; char *description; char *history; unsigned long historylen; char *filters; char currenttime[80]; EBS_FILE *ebs_file; FILE *file; } header; struct header_internal { void *pointer_to_file; int file_length; int data_length; int fd; int samples_start_pos; } header_internal; void *checkmalloc (int size) { void *ptr; ptr= malloc (size); if (ptr== NULL) { perror ("Error allocating memory (malloc)"); abort (); } return (ptr); } void *checkrealloc (void *ptr_in, int size) { void *ptr; if (ptr_in== NULL) { ptr= malloc (size); if (ptr== NULL) { perror ("Error allocating memory (realloc1)"); abort (); } return (ptr); } ptr= realloc (ptr_in, size); if (ptr== NULL && size!= 0) { perror ("Error allocating memory (realloc2)"); abort (); } return (ptr); } char *checkstrdup (char *string2) { char *string; string= strdup (string2); if (string== NULL) { perror ("Error allocating memory (strdup)"); abort (); } return (string); } #define BUFSIZE 3000 int OpenEBSFile (char *name) { int result; struct stat buf; ebs_fixedheader fixed; void *ptr; unsigned long length; int i, fin; char text [BUFSIZE], text2 [30]; int min, max; struct tm tm; /* Determine size of EBS file */ result= stat (name, &buf); if (result!= 0) {perror ("Stat: "); return (-1);} header_internal.file_length= buf.st_size; /* Open the EBS file */ header.ebs_file= ebs_open (name, 'r'); if (header.ebs_file== NULL) {fprintf (stderr, "'%s': no valid EBS file\n", name); return (-1);} /* Get the fixed header */ ebs_getfixedheader (header.ebs_file, &fixed); /* Check EBS encoding */ switch (i= fixed.encoding_id) { case EBS_CIB_16: /* case EBS_TIB_16: */ case EBS_CIL_16: /* case EBS_TIL_16: */ header.ebs_type= i; break; default: fprintf(stderr, "Input file is not in supported EBS format!\n"); ebs_close (header.ebs_file); return (-1); } /* Store name of EBS file */ header.filename= checkstrdup (name); /* Check size of EBS file */ header.number_of_electrodes= fixed.channels; /* Check unspezified number of samples */ if ((fixed.sampleshigh== 0xffffffff && fixed.sampleslow== 0xffffffff) && (header.ebs_type== EBS_CIB_16 || header.ebs_type== EBS_CIL_16)) { fprintf(stderr, "CIB_16 and CIL_16 not allowed " "with unspecified number of samples\n"); ebs_close (header.ebs_file); return (-1);} /* Check number of samples */ if (fixed.sampleshigh!= 0 && !(fixed.sampleshigh== 0xffffffff && fixed.sampleslow== 0xffffffff)) { fprintf (stderr, "Number per samples > 4GB\n"); ebs_close (header.ebs_file); return (-1); } /* Check number of electrodes */ if (header.number_of_electrodes<= 0) {fprintf (stderr, "Number of electrodes must be >0\n"); ebs_close (header.ebs_file); return (-1);} /* Store beginning of data part */ header_internal.samples_start_pos= ebs_data_offset (header.ebs_file); /* Check size of data part */ if (fixed.datalengthhigh== 0xffffffff && fixed.datalengthlow== 0xffffffff) header_internal.data_length= header_internal.file_length- header_internal.samples_start_pos; else if (fixed.datalengthhigh!= 0 || fixed.datalengthlow> 0x20000000) { fprintf (stderr, "file too long\n"); ebs_close (header.ebs_file); return (-1);} else header_internal.data_length= fixed.datalengthlow << 2; /* Unspecified number of samples */ if (fixed.sampleslow== 0xffffffff) header.samples_per_channel= (header_internal.data_length/ 2)/ fixed.channels; else { header.samples_per_channel= fixed.sampleslow; if (header_internal.data_length!= fixed.sampleslow* fixed.channels* 2) {fprintf (stderr, "number of samples and number of electrodes do not " "match filesize\n"); ebs_close (header.ebs_file); return (-1);} } /* Institution */ header.institution= &header.null; if (!anonymous) { ptr= ebs_getattr (header.ebs_file, EBS_INSTITUTION, &length); if (ptr!= NULL) { gets4_cs (text, BUFSIZE, EBS_CS_LATIN1, &ptr); header.institution= checkstrdup (text); } } /* Patient name */ header.patientname= &header.null; if (!anonymous) { ptr= ebs_getattr (header.ebs_file, EBS_PATIENT_NAME, &length); if (ptr!= NULL) { gets4_cs (text, BUFSIZE, EBS_CS_LATIN1, &ptr); header.patientname= checkstrdup (text); } } /* Patient name */ header.patientid= &header.null; if (!anonymous) { ptr= ebs_getattr (header.ebs_file, EBS_PATIENT_ID, &length); if (ptr!= NULL) { gets4_cs (text, BUFSIZE, EBS_CS_LATIN1, &ptr); header.patientid= checkstrdup (text); } } /* Patient sex */ header.patientsex= &header.null; ptr= ebs_getattr (header.ebs_file, EBS_PATIENT_SEX, &length); if (ptr!= NULL) { i= geti32 (&ptr); if (i== 1) header.patientsex= checkstrdup ("male"); if (i== 2) header.patientsex= checkstrdup ("female"); } /* Patient birthday */ header.patientbirthday= &header.null; ptr= ebs_getattr (header.ebs_file, EBS_PATIENT_BIRTHDAY, &length); if (ptr!= NULL) { strncpy (text, (char *) ptr, 16); if (length == 2 && isdigit(text[ 0]) && isdigit(text[ 1]) && isdigit(text[ 2]) && isdigit(text[ 3]) && isdigit(text[ 4]) && isdigit(text[ 5]) && isdigit(text[ 6]) && isdigit(text[ 7])) { if (anonymous) sprintf (text2, "%.4s", text); else sprintf (text2, "%.4s-%.2s-%.2s", text, text+ 4, text+ 6); header.patientbirthday= checkstrdup (text2); } } /* Short description */ header.shortdescription= &header.null; if (!anonymous) { ptr= ebs_getattr (header.ebs_file, EBS_SHORT_DESCRIPTION, &length); if (ptr!= NULL) { gets4_cs (text, BUFSIZE, EBS_CS_LATIN1, &ptr); header.shortdescription= checkstrdup (text); } } /* Description */ header.description= &header.null; if (!anonymous) { ptr= ebs_getattr (header.ebs_file, EBS_DESCRIPTION, &length); if (ptr!= NULL) { header.description= (char *) checkmalloc ((length*2+1)* sizeof (char)); gets4_cs (header.description, length*2, EBS_CS_LATIN1, &ptr); } } /* Processing history */ header.history= NULL; header.historylen= 0; if (!anonymous) { ptr= ebs_getattr (header.ebs_file, EBS_PROCESSING_HISTORY, &length); if (ptr!= NULL) { header.history= (char *) checkmalloc ((length*4)* sizeof (char)); memcpy (header.history, ptr, length* 4); header.historylen= length* 4; } } /* Filters */ header.filters= NULL; if (!anonymous) { ptr= ebs_getattr (header.ebs_file, EBS_FILTERS, &length); if (ptr!= NULL) { header.filters= (char *) checkmalloc (length* 4* sizeof (char)); memcpy (header.filters, ptr, length* 4); } } header.recordingdate= &header.null; header.recordingtime= NULL; header.starttime= (time_t) 0; ptr= ebs_getattr (header.ebs_file, EBS_RECORDING_TIME, &length); if (ptr!= NULL) { time_t current_time; strncpy (text, (char *) ptr, 16); if ((length== 4 && text [8]== 'T' && text [15]== '\0' && isdigit(text[ 0]) && isdigit(text[ 1]) && isdigit(text[ 2]) && isdigit(text[ 3]) && isdigit(text[ 4]) && isdigit(text[ 5]) && isdigit(text[ 6]) && isdigit(text[ 7]) && isdigit(text[ 9]) && isdigit(text[10]) && isdigit(text[11]) && isdigit(text[12]) && isdigit(text[13]) && isdigit(text[14])) || (length == 2 && isdigit(text[ 0]) && isdigit(text[ 1]) && isdigit(text[ 2]) && isdigit(text[ 3]) && isdigit(text[ 4]) && isdigit(text[ 5]) && isdigit(text[ 6]) && isdigit(text[ 7]))) { sprintf (text2, "%.4s-%.2s-%.2s", text, text+ 4, text+ 6); header.recordingdate= checkstrdup (text2); if (length== 4) { sprintf (text2, "%.2s:%.2s:%.2s", text+ 9, text+ 11, text+ 13); header.recordingtime= checkstrdup (text2); sscanf (text, "%4d%2d%2dT%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,&tm.tm_min, &tm.tm_sec); tm.tm_year-= 1900; tm.tm_mon--; tm.tm_wday= -1; tm.tm_yday= -1; tm.tm_isdst= -1; header.starttime= mktime (&tm); if (header.starttime== (time_t)-1) { header.starttime= (time_t) 0; free (header.recordingtime); header.recordingtime= NULL; } } } } /* get sample rate */ ptr= ebs_getattr (header.ebs_file, EBS_SAMPLE_RATE, &length); if (ptr== NULL) header.sample_rate= 1.0; else { header.sample_rate= getf4 (&ptr, &result); if (result>= 0) header.sample_rate_specified= 1; else header.sample_rate= 1.0; } /* Get electrode units and scalings */ header.electrode_unit= (char **) checkmalloc (header.number_of_electrodes* sizeof (char *)); header.electrode_scale= (float *) checkmalloc (header.number_of_electrodes* sizeof (float)); ptr= ebs_getattr (header.ebs_file, EBS_UNITS, &length); if (ptr== NULL) { for (i= 0; i< header.number_of_electrodes; ++i) { header.electrode_unit [i]= checkstrdup ("bins"); header.electrode_scale [i]= 1.0; } } else { for (i= 0; i< header.number_of_electrodes; ++i) { header.electrode_scale [i]= getf4 (&ptr, &result); gets4_cs (text, BUFSIZE, EBS_CS_LATIN1, &ptr); if (result== 1) { /* unspecified scaling */ header.electrode_unit [i]= checkstrdup ("bins"); header.electrode_scale [i]= 1.0; } else /* error or all right */ if (*text== '\0') header.electrode_unit [i]= checkstrdup ("bins"); else header.electrode_unit [i]= checkstrdup (text); } } /* Get channel description */ header.electrode_name= (char **) checkmalloc (header.number_of_electrodes* sizeof (char *)); ptr= ebs_getattr (header.ebs_file, EBS_CHANNEL_DESCRIPTION, &length); if (ptr== NULL) { for (i= 0; i< header.number_of_electrodes; ++i) { sprintf (text, "%d", i+ 1); header.electrode_name [i]= checkstrdup (text); } } else { for (i= 0; i< header.number_of_electrodes; ++i) { /* get short description */ gets4_cs (text, BUFSIZE, EBS_CS_LATIN1, &ptr); if (text[0]!= '\0') header.electrode_name [i]= checkstrdup (text); else { sprintf (text, "%d", i+ 1); header.electrode_name [i]= checkstrdup (text); } /* ignore additional description */ gets4_cs (text, BUFSIZE, EBS_CS_LATIN1, &ptr); } } /* get preferred integer range */ header.preferred_range_min= (int *) checkmalloc (header.number_of_electrodes* sizeof (int)); header.preferred_range_max= (int *) checkmalloc (header.number_of_electrodes* sizeof (int)); ptr= ebs_getattr (header.ebs_file, EBS_PREFERRED_INTEGER_RANGE, &length); if (ptr== NULL) { for (i= 0; i< header.number_of_electrodes; ++i) { header.preferred_range_min [i]= -32768; header.preferred_range_max [i]= 32767; } } else { for (i= 0; i< header.number_of_electrodes; ++i) { min= geti32 (&ptr); max= geti32 (&ptr); if (min== max) { header.preferred_range_min [i]= -32768; header.preferred_range_max [i]= 32767; } else { header.preferred_range_min [i]= min; header.preferred_range_max [i]= max; } } } /* check for errors */ if (ebs_get_error_num (header.ebs_file)) { fprintf (stderr, "Error reading EBS_ file: %s\n", ebs_error_str (header.ebs_file)); ebs_close (header.ebs_file); return (-1); } header.file= ebs_stream (header.ebs_file); header_internal.fd= fileno (ebs_stream (header.ebs_file)); return (0); } int ReadSingleScaling (char *in) { float value; char text [10]; if (sscanf (in, "%f%9s", &value, text)!= 2) { fprintf (stderr, "Illegal scaling: '%s'/cm\n", in); return (-1); } text[9]='\0'; yscale= checkrealloc (yscale, (nyscales+1)* sizeof (struct yscale)); strcpy (yscale[nyscales].unit, text); yscale[nyscales].scale= value; nyscales++; return (0); } int ReadScalings (char *in) { char *string, *ptr, *next, *act; int i, j, len= strlen(in); /* Copy string and remove all spaces */ string= (char *) checkmalloc ((len+1)*sizeof(char)); for (i= j= 0; i< len; ++i) if (in[i]!= ' ') string [j++]=in[i]; string [j]= '\0'; if (j==0) {free (string); return (0);} ptr= string; while ((act= strchr (ptr, ','))!= NULL) { next= act+1; *act= '\0'; if (ReadSingleScaling (ptr)< 0) {free (string); return (-1);} ptr= next; } if (*ptr== '\0') {free (string); return (0);} if (ReadSingleScaling (ptr)< 0) {free (string); return (-1);} free (string); return (0); } char *conv (unsigned char *in) { int i, inlen= strlen (in); char *ptr; static unsigned char table [256][5], len [256], undef=1; static char out [BUFSIZE]; if (undef) { undef= 0; for (i= 0; i< 256; ++i) { table [i][0]= '?'; table [i][1]= '\0'; len [i]= 1; } /* ASCII */ for (i= 32; i<= 126; i++) { table [i][0]= i; table [i][1]= '\0'; len [i]= 1; } /* ISO latin 1 */ for (i= 160; i<= 255; i++) { sprintf (table[i], "\\%o", i); len [i]= 4; } /* Special characters */ table ['('][0]= '\\'; table ['('][1]= '('; table ['('][2]= '\0'; len ['(']= 2; table [')'][0]= '\\'; table [')'][1]= ')'; table [')'][2]= '\0'; len [')']= 2; table ['\\'][0]= '\\'; table ['\\'][1]= '\\'; table ['\\'][2]= '\0'; len ['\\']= 2; } out[0]='\0'; ptr= out; for (i= 0; i< inlen; ++i) { strcpy (ptr, table [in[i]]); ptr+= len [in[i]]; } return (out); } void PrintText2 (FILE *fout, char *in) { int max= 64; char line [65]; int i, c, len= strlen (in); /* print max 64 characters/line */ c= 0; fprintf (fout, "SmallFont setfont\n"); for (i= 0; i< max; ++i) line[i]='M'; line [64]= '\0'; /* fprintf (fout, "(%s) p\n", conv (line)); */ for (i= 0; i< max; ++i) line[i]='W'; line [64]= '\0'; /* fprintf (fout, "(%s) p\n", conv (line)); */ for (i= 0; i< len; ++i) { if (in [i]== '\n' || c== max) { line [c]= '\0'; fprintf (fout, "(%s) p\n", conv (line)); c= 0; } if (in [i]!= '\n') line [c++]= in [i]; } /* print remaining text */ if (c> 0) { line [c]= '\0'; fprintf (fout, "(%s) p\n", conv (line)); } } void PrintText (FILE *fout, char *in) { /* indent */ fprintf (fout,"indent\n"); PrintText2 (fout, in); /* Move cursor to original indent */ fprintf (fout,"noindent\n"); } void PrintHistory (FILE *fout, char *history, unsigned long len) { char *buf; void *end= (void *) (history+ len); void *ptr= (void *) history; if (history== NULL || len== 0) return; buf= (char *) checkmalloc ((len+1)* sizeof (char)); while (ptr< end) { /* indent */ fprintf (fout, "SmallFont setfont\n"); fprintf (fout,"(\\200 ) extraindent\n"); gets4_cs (buf, len, EBS_CS_LATIN1, &ptr); PrintText2 (fout, buf); /* Move cursor to original indent */ fprintf (fout,"noindent\n"); } free (buf); } void PrintFilters (FILE *fout, void *ptr) { int i, j, nan; long l; double f; unsigned long ua; static char string[BUFSIZE], string_old[BUFSIZE], *filter_text; char text [40]; i= 0; l = 0; for (j = 0; j <= header.number_of_electrodes; j++) { if (0 == j) filter_text = string_old; else filter_text = string; if (j < header.number_of_electrodes) { if (electrode[i]!= j) { /* skip filters */ ua = geti32(&ptr); f = getf4(&ptr, &nan); f = getf4(&ptr, &nan); } else { i++; filter_text[0] = '\0'; while ((ua = geti32(&ptr)) != 0xffffffffL && strlen(filter_text) < BUFSIZE - 100) { strcat(filter_text, " "); if (1 == ua) strcat(filter_text, "lowpass"); else if (2 == ua) strcat(filter_text, "highpass"); else if (3 == ua) strcat(filter_text, "notch"); else strcat(filter_text, "unknown"); f = getf4(&ptr, &nan); if (!nan) { sprintf(filter_text + strlen(filter_text), " filter, %g Hz", f); if (2 == ua && f > 0.0) { if (1/(2*PI*f) < 1.0) sprintf(filter_text + strlen(filter_text), " (t=%g ms)", 1000/(2*PI*f)); else sprintf(filter_text + strlen(filter_text), " (t=%g sec)", 1/(2*PI*f)); } } else strcat(filter_text, " filter, ??? Hz"); f = getf4(&ptr, &nan); if (nan == 0) sprintf(filter_text + strlen(filter_text), ", %g dB/decade falloff", f); else if (nan != 1) strcat(filter_text, ", ??? dB/decade falloff"); strcat(filter_text, "\n"); } } } if (j > 0 && (j == header.number_of_electrodes || strcmp(string,string_old) != 0)) { if (l == i-1) { sprintf (text, "channel%3d:", l+1); PrintText (fout, text); PrintText (fout, string_old); } else { sprintf (text, "channel%3d -%3d:", l+1, i); PrintText (fout, text); PrintText (fout, string_old); } l = i; strcpy(string_old, string); } } } void PrintScalings (FILE *fout) { static char string[BUFSIZE], string_old[BUFSIZE], *scale; int l, j; char text [40]; l = 0; for (j = 0; j <= nelectrodes; j++) { if (0 == j) scale = string_old; else scale = string; if (j < nelectrodes) sprintf (scale, "%.2f %s/cm", electrodescale[electrode[j]].scale, electrodescale[electrode[j]].unit); if (j > 0 && (j == nelectrodes || strcmp(string,string_old) != 0)) { if (l == j-1) { sprintf (text, "channel%3d: %s", l+1, string_old); PrintText (fout, text); } else { sprintf (text, "channel%3d -%3d: %s", l+1, j, string_old); PrintText (fout, text); } l = j; strcpy(string_old, string); } } } char *GetDate (time_t t, enum timeformat format) { static char text [31]; struct tm *tp; if (header.recordingtime== NULL) { int sec= (int) t, min, hour; hour= sec/ (60*60); sec-= hour*60*60; min= sec/60; sec-= min*60; if (format== onlytime || format== timeanddate) { sprintf (text, "%02d:%02d:%02d", hour, min, sec); return (text); } text[0]='\0'; return (text); } tp= localtime (&t); if (tp== NULL) {text[0]='\0'; return (text);} if (format== onlytime) { strftime (text, 30, "%H:%M:%S", tp); return (text); } if (format== onlydate) { strftime (text, 30, "%Y-%m-%d", tp); return (text); } strftime (text, 30, "%Y-%m-%d %H:%M:%S", tp); return (text); } char *GetLength (unsigned long sec) { int min, hour, day; static char text [30]; day= sec/ (60*60*24); sec-= day*60*60*24; hour= sec/ (60*60); sec-= hour*60*60; min= sec/60; sec-= min*60; if (day== 0) sprintf (text, "%02d:%02d:%02d", hour, min, sec); else sprintf (text, "%d days %02d:%02d:%02d", day, hour, min, sec); return (text); } void PrintTitle (FILE *fout) { int minx, miny, width, height, aux, maxx, maxy, borderx, bordery; int centerx, quarterx, offset; time_t today; char text [BUFSIZE]; maxx= paper [paperno].maxx; maxy= paper [paperno].maxy; borderx= paper [paperno].borderx; bordery= paper [paperno].bordery; if (!paper [paperno].rotate) { aux= maxx; maxx= maxy; maxy= aux; aux= borderx; borderx= bordery; bordery= aux; offset= paper [paperno].maxx; } else offset= paper [paperno].maxy; minx= MMTOPOINTS (borderx* 2); miny= MMTOPOINTS (maxy- bordery* 2); width= MMTOPOINTS (maxx- borderx* 3); height= MMTOPOINTS (maxy- bordery* 3); fprintf (fout, "%%%%Page: Title %d\n", page++); fprintf (fout, "%%%%PageOrientation: Landscape\n"); fprintf (fout, "%%%%PageResources: font Helvetica Helvetica-Bold Courier\n"); fprintf (fout, "%%%%BeginPageSetup\n"); /* rotate */ fprintf (fout, "%% move and rotate orign\n" "90 rotate\n" "0 %d translate\n", MMTOPOINTS (-offset)); fprintf (fout, "%%%%EndPageSetup\n"); fprintf (fout, "/bottom %d def\n", MMTOPOINTS (bordery)); fprintf(fout, "/NormalFont /Helvetica-ISO findfont %g scalefont def\n" "/BoldFont /Helvetica-Bold-ISO findfont %g scalefont def\n" "/SmallFont /Courier-ISO findfont %g scalefont def\n", NORMALHEIGHT, BOLDHEIGHT, SMALLHEIGHT); centerx= minx+ width/2; quarterx= (centerx+ minx)/ 2; /* copyright notice */ fprintf (fout, "/Helvetica-ISO findfont 8 scalefont setfont\n" "(%s) dup\nstringwidth pop 2 div %d exch sub %d moveto show\n", version_short, MMTOPOINTS (maxx>>1), miny); /* left part of page */ fprintf (fout, "/xleft %d def\n", minx); fprintf (fout, "%d %d moveto\n", minx, miny); fprintf (fout, "noindent\n"); /* Institution */ fprintf (fout, "(%s) bp nl nl nl\n", conv (header.institution)); /* Patientname */ fprintf (fout, "(%s) stab\n", conv ("Name ")); fprintf (fout, "(%s)", conv ("Name")); fprintf (fout, " (%s) bnp nl\n", conv (header.patientname)); /* Patientid */ fprintf (fout, "(%s)", conv ("ID")); fprintf (fout, " (%s) bnp nl\n", conv (header.patientid)); /* Patientsex */ fprintf (fout, "(%s)", conv ("Sex")); fprintf (fout, " (%s) bnp\n", conv (header.patientsex)); /* Patientbirthday */ fprintf (fout, "%d currentpoint exch pop moveto\n", quarterx); fprintf (fout, "(%s)", conv ("Birthday ")); fprintf (fout, " (%s) bnp1 nl\n", conv (header.patientbirthday)); /* Recorded at */ if (header.recordingtime!= NULL) { fprintf (fout, "(%s) stab\n", conv ("Recording start ")); sprintf (text, "%s %s", header.recordingdate, header.recordingtime); fprintf (fout, "(%s) (%s) bnp nl\n", conv ("Recording start"), text); } else { fprintf (fout, "(%s) stab\n", conv ("Recording date ")); fprintf (fout, "(%s) (%s) bnp nl\n", conv ("Recording date"), header.recordingdate); } if (header.recordingtime!= NULL && header.sample_rate_specified) fprintf (fout, "(%s) (%s) bnp nl\n", conv ("Recording end"), GetDate (header.starttime+ (time_t) (header.samples_per_channel/ header.sample_rate), timeanddate)); if (header.sample_rate_specified) fprintf (fout, "(%s) (%s) bnp nl nl\n", conv ("Recording time"), GetLength (header.samples_per_channel/header.sample_rate)); else fprintf (fout, "nl\n"); /* Printed intervall */ if (start== 0 && length== header.samples_per_channel) { fprintf (fout, "(%s)", conv ("Printed")); sprintf (text, "\\(%d %s\\)", pages, pages==1?conv ("page"):conv ("pages")); fprintf (fout, "(%s %s) bnp nl nl\n", conv ("entire recording"), text); } else { if (start==0) { fprintf (fout, "(%s)", conv ("Printed from")); fprintf (fout, "(%s) bnp nl\n", conv ("begin of the recording")); } else fprintf (fout, "(%s) (%s) bnp nl\n", conv ("Printed from"), GetDate (header.starttime+ (time_t) (start/header.sample_rate), timeanddate)); if (start+length== header.samples_per_channel) { fprintf (fout, "(%s)", conv ("Printed to")); fprintf (fout, "(%s) bnp nl\n", conv ("end of the recording")); } else fprintf (fout, "(%s) (%s) bnp nl\n", conv ("Printed to"), GetDate (header.starttime+ (time_t) ((start+length)/ header.sample_rate), timeanddate)); if (header.sample_rate_specified) { sprintf (text, "%s \\(%d %s\\)", GetLength ((int)ceil((double)(length/header.sample_rate))), pages, pages==1?conv ("page"):conv ("pages")); fprintf (fout, "(%s) (%s) bnp nl nl\n", conv ("Printed"), text); } else fprintf (fout, "nl\n"); } /* Short description */ fprintf (fout, "(%s) bp nl\n", conv ("Short description")); PrintText (fout, header.shortdescription); /* Description */ fprintf (fout, "nl (%s) bp nl\n", conv ("Description")); PrintText (fout, header.description); /* right part of page */ fprintf (fout, "/xleft %d def\n", centerx); fprintf (fout, "%d %d moveto\n", centerx, miny); fprintf (fout, "noindent\n"); /* Current time and date */ header.currenttime[0]='\0'; if ((today= time (NULL))!= (time_t)-1) { struct tm *tp= localtime (&today); if (tp!= NULL) { char text[22]; fprintf (fout, "NormalFont setfont\n"); strftime (text, 20, "%Y-%m-%d", tp); fprintf (fout, "%d (%s) tr nl\n", minx+ width, text); strftime (text, 20, "%H:%M:%S", tp); fprintf (fout, "%d (%s) tr nl nl\n", minx+ width, text); strftime (header.currenttime, 40, "%Y-%m-%d %H:%M:%S", tp); } } /* Filename */ fprintf (fout, "(%s) stab\n", conv ("Paper speed ")); fprintf (fout, "(%s)", conv ("Filename")); fprintf (fout, " (%s) bnp nl\n", conv (header.filename)); /* Printerresolution */ if (header.sample_rate_specified) sprintf (text, "%d dots/cm \\(%d dpi, %d dots/s\\)", (int) (dpi/ 25.4*10.0), (int) dpi, (int) dots_per_sec); else sprintf (text, "%d dots/cm \\(%d dpi\\)", (int) (dpi/ 25.4* 10.0), (int) dpi); fprintf (fout, "(%s) (%s) bnp nl nl\n", conv ("Resolution"), text); /* Printed from */ #ifndef MSDOS { char *string; struct passwd *passwd; string= cuserid (NULL); if (string!= NULL && *string!= 0) passwd= getpwnam (string); else passwd= getpwuid (getuid ()); if (passwd!= NULL) { fprintf (fout, "(%s)", conv ("Printed by")); fprintf (fout, " (%s) bnp nl\n", conv (passwd->pw_gecos)); } if (gethostname (text, 40)>= 0) { fprintf (fout, "(%s)", conv ("Printed on")); fprintf (fout, " (%s) bnp nl nl\n", conv (text)); } else if (passwd!= NULL) fprintf (fout, "nl\n"); } #endif /* Samplerate */ fprintf (fout, "(%s) (%.2f Hz) bnp nl nl\n", conv ("Samplerate"), header.sample_rate); /* x resolution */ fprintf (fout, "(%s) (%d mm/s) bnp nl nl\n", conv ("Paper speed"), mm_per_sec); /* y resolution */ fprintf (fout, "(%s) bp nl\n", conv ("Scalings")); PrintScalings (fout); fprintf (fout, "nl\n"); /* Filters */ if (header.filters!= NULL) { fprintf (fout, "(%s) bp nl\n", conv ("Filters")); PrintFilters (fout, (void *) header.filters); fprintf (fout, "nl\n"); } /* Processing history */ fprintf (fout, "(%s) bp nl\n", conv ("Processing history")); PrintHistory (fout, header.history, header.historylen); /* Print this page */ fprintf (fout, "showpage\n"); } void GetLine (unsigned long from, unsigned long channel, double scale, int no, int *buf) { if (header.ebs_type== EBS_CIB_16) { unsigned long ptr= header_internal.samples_start_pos+ header.samples_per_channel* channel* 2 + from* 2; int i, act, next; fseek (header.file, ptr, SEEK_SET); act= 0; for (i= 0; i< no; ++i) { buf [i]= fgeti16 (header.file); act++; next= (int) (i* scale); if (next!= act) { fseek (header.file, (next-act)* 2, SEEK_CURRENT); act= next; } } } } void PrintLine (FILE *fout, int x, int y, double scale, int no, int *buf) { int i, c, s, p, max= 200; /* split polygon */ s= 0; p= 0; while (s< no) { c= no- s; if (c> max) c= max; fprintf (fout, "%d %d [", x+ s, y); if (p!= 0) fprintf (fout, " %d", (int) (buf [p-1]* scale)); for (i= 0; i< c; ++i) fprintf (fout, " %d", (int) (buf [p++]* scale)); fprintf (fout, "] dc\n"); s+= c; } fprintf (fout, "\n"); } char *ASCII94 (FILE *fout, int in) { if (in< -4400) {in= -4400; fprintf (stderr, "%d too small\n", in);} if (in> 4400) {in= 4400; fprintf (stderr, "%d too big\n", in);} in+= 4400; fputc (33+ (in/94), fout); fputc (33+ (in%94), fout); } void PrintLine2 (FILE *fout, double scale, int no, int *buf) { int i, c, s, p, max= 119; /* split polygon */ s= 0; p= 0; while (s< no) { c= no- s; if (c> max) c= max; if (p!= 0) ASCII94 (fout, (int) (buf [p-1]* scale)); for (i= 0; i< c; ++i) ASCII94 (fout, (int) (buf [p++]* scale)); fprintf (fout, "\n"); s+= c; } } int GetPaper (char *in) { int i, len; /* convert to lowercase */ len= strlen (in); for (i= 0; i< len; ++i) in[i]=tolower (in[i]); i=0; while (*paper[i].name!= '\0') { if (strcmp (paper[i].name, in)== 0) return (i); i++; } return (-1); } int main (int argc, char **argv) { FILE *fin, *fout= stdout; char *fnin = NULL; /* input file name */ char *fnout = NULL; /* output file name */ long i, j; unsigned long from; long outcode = (long) 0xffffffffL; int *buf; int secs, per_page; double xscale; int xoffset, yoffset, x, y; float height; int showtitle= 1, chanheight, zerolines= 0; int maxx, maxy, borderx, bordery, ytext, aux, samples_per_screen; time_t actsec; char *string; /* do all the command line and file open stuff */ fin= stdin; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') for (j = 1; j < 2000 && argv[i][j] != 0; j++) switch (argv[i][j]) { case 'c': case 'C': fprintf (stderr, copyright); exit (1); case 'a': case 'A': anonymous= 1; break; case 't': case 'T': showtitle= 0; break; case 'z': case 'Z': zerolines= 1; break; case 'r': case 'R': if (argv[i][j+1] != '\0') { if (sscanf (argv[i]+j+1, "%d", &aux)!= 1 || aux< 50 || aux> 5000){ fprintf(stderr, "Invalid resolution: '%s'\n", argv[i]+j+1); exit(1); } dpi= aux; j = 9999; } else { fprintf(stderr, usage, version, argv[0]); exit(1); } break; case 'p': case 'P': if (argv[i][j+1] != '\0') { if ((paperno= GetPaper (argv[i]+j+1))< 0) { fprintf(stderr, "Invalid paper: '%s'\n", argv[i]+j+1); exit(1); } j = 9999; } else { fprintf(stderr, usage, version, argv[0]); exit(1); } break; case 'x': case 'X': if (argv[i][j+1] != '\0') { if (sscanf (argv[i]+j+1, "%d", &aux)!= 1 || aux<= 1 || aux> 1000){ fprintf(stderr, "Invalid mm/sec: '%s'\n", argv[i]+j+1); exit(1); } mm_per_sec= aux; j = 9999; } else { fprintf(stderr, usage, version, argv[0]); exit(1); } break; case 'y': case 'Y': if (ReadScalings (argv[i]+j+1)< 0) exit(1); j = 9999; break; case 'i': case 'I': if (sscanf (argv[i]+j+1, "%d,%d", &start, &length)!=2) { fprintf(stderr, "Invalid mm/sec: '%s'\n", argv[i]+j+1); exit(1); } j = 9999; break; default: fprintf(stderr, usage, version, argv[0]); exit(1); } else if (fnin== NULL) { fnin= argv [i]; fin = fopen(fnin, "rb"); if (fin == NULL) { fprintf(stderr, "Can't open input file '%s", fnin); perror("'"); exit(1); } } else if (fnout== NULL) { fnout= argv [i]; fout = fopen(fnout, "wb"); if (fout == NULL) { fprintf(stderr, "Can't open output file '%s", fout); perror("'"); exit(1); } } else { fprintf(stderr, usage, version, argv[0]); exit(1); } } /* Open EBS file and read header */ if (OpenEBSFile (fnin)) exit (1); /* if no electrodes are given, then print'em all */ if (electrode== NULL) { nelectrodes= header.number_of_electrodes; electrode= (int *) checkmalloc (nelectrodes* sizeof (int)); for (i= 0; i< nelectrodes; ++i) electrode [i] = i; } else for (i= 0; i< nelectrodes; ++i) if (electrode [i]>= header.number_of_electrodes) { fprintf (stderr, "You can't select electrode %d, " "there are only %d electrodes\n", electrode [i]+ 1, header.number_of_electrodes); exit (1); } maxx= paper [paperno].maxx; maxy= paper [paperno].maxy; borderx= paper [paperno].borderx; bordery= paper [paperno].bordery; start= ((int)(start/header.sample_rate+0.5))*header.sample_rate; if (start>= header.samples_per_channel) { fprintf(stderr, "You can't start at position %ld\n" "because the recording contains only %ld samples\n", start, header.samples_per_channel); exit (1); } if (length!= 0xffffffff && start+length> header.samples_per_channel) fprintf (stderr, "You can't read samples beyond the end of the recording.\n" "The systems will print only until the end of the recording.\n"); if (length== 0xffffffff) length= header.samples_per_channel-start; else length= (ceil((double)(length/header.sample_rate)))*header.sample_rate; if (start+ length> header.samples_per_channel) length= header.samples_per_channel-start; secs= (paper [paperno].maxx- 2* paper [paperno].borderx)/ mm_per_sec; xscale= (double) header.sample_rate/ ((double)(mm_per_sec)/25.4*dpi); if (header.sample_rate_specified) dots_per_sec= mm_per_sec/25.4*dpi; if (xscale< 1.0) { xscale= 1.0; dpi= (double) header.sample_rate/ ((double)(mm_per_sec)/25.4*xscale); if (header.sample_rate_specified) dots_per_sec= header.sample_rate; } per_page= MMTOXRES (mm_per_sec* secs)+ 1; buf= (int *) checkmalloc (per_page* sizeof (int)); samples_per_screen= secs* header.sample_rate+ 0.5; pages= ceil ((double) length/ samples_per_screen); actsec= header.starttime+ (time_t) (start/header.sample_rate+0.5); x= MMTOXRES (maxx- secs* mm_per_sec)/ 2; x= MMTOXRES (maxx- borderx- secs* mm_per_sec); yoffset= 10; /* 1cm for headline */ height= (float) ((maxy- 2* bordery- yoffset)*YUNIT)/ nelectrodes; ytext= (maxy- bordery- DESCHEIGHT/72.0*25.4)* YUNIT; /* Determine yscalings */ electrodescale= (struct yscale *) checkmalloc (nelectrodes* sizeof (struct yscale)); for (i= 0; i< nelectrodes; ++i) { electrodescale[i].unit[0]='\0'; for (j= 0; j< nyscales; ++j) if (strcmp (header.electrode_unit [electrode [i]], yscale[j].unit)== 0) { electrodescale[i]= yscale[j]; break; } if (electrodescale[i].unit[0]=='\0') { /* default scalings */ if (strcmp (header.electrode_unit [electrode [i]], "µV")== 0) { strcpy (electrodescale[i].unit, "µV"); electrodescale[i].scale= 70.0; /* 70uV/cm */ } if (strcmp (header.electrode_unit [electrode [i]], "bins")== 0) { strcpy (electrodescale[i].unit, "bins"); electrodescale[i].scale= 2000.0; /* 2000bins/cm */ } if (electrodescale[i].unit[0]=='\0') { fprintf (stderr, "Sorry, don't know how to scale '%s'\n", header.electrode_unit [i]); exit (1); } } } /* print PS header */ fprintf (fout, "%%!PS-Adobe-3.0\n"); fprintf (fout, "%%%%BoundingBox: %d %d %d %d\n", MMTOPOINTS (borderx), MMTOPOINTS (bordery), MMTOPOINTS (maxx- borderx), MMTOPOINTS (maxy- bordery)); fprintf (fout, "%%%%Creator: %s\n", version_short_asc); if (header.currenttime[0]!='\0') fprintf (fout, "%%%%CreationDate: %s\n", header.currenttime); fprintf (fout, "%%%%DocumentData: Clean7Bit\n"); if (header.institution[0]!='\0') fprintf (fout, "%%%%For: %s\n", header.institution); fprintf (fout, "%%%%LanguageLevel: 2\n"); fprintf (fout, "%%%%Pages: %d\n", showtitle?pages+1:pages); fprintf (fout, "%%%%PageOrder: Ascend\n"); fprintf (fout, "%%%%Title: Recording\n"); fprintf (fout, "%%%%DocumentMedia: Plain %d %d 0 () ()\n", MMTOPOINTS (maxx), MMTOPOINTS (maxy)); fprintf (fout, "%%%%DocumentNeededResources: " "font Courier Helvetica Helvetica-Bold\n"); fprintf (fout, "%%%%EndComments\n"); fprintf (fout, "%%%%BeginDefaults\n"); fprintf (fout, "%%%%PageBoundingBox: %d %d %d %d\n", MMTOPOINTS (borderx), MMTOPOINTS (bordery), MMTOPOINTS (maxx- borderx), MMTOPOINTS (maxy- bordery)); fprintf (fout, "%%%%PageOrientation: %s\n", paper[paperno].rotate?"Landscape":"Portrait"); fprintf (fout, "%%%%PageResources: font Helvetica\n"); fprintf (fout, "%%%%EndDefaults\n"); fprintf (fout, "%%%%BeginProlog\n"); fprintf (fout, ps_procs); fprintf (fout, "%% Setup page\n" "/sp {\n"); /* rotate */ if (paper [paperno].rotate) fprintf (fout, " 90 rotate\n" " 0 %d translate\n", (int) ((float) (-paper [paperno].maxy)/25.4*72)); /* set scale */ fprintf (fout, " 72 %g div 72 %d div scale\n", dpi, (int) (25.4*YUNIT)); fprintf (fout, "} def\n\n"); fprintf (fout, "%% Init page\n" "/ip {\n" " /p exch def\n" " /d exch def\n" " /ary exch def\n" " /ymax exch def\n" " /ymin exch def\n"); /* set line width */ fprintf (fout, " 0 setlinewidth\n"); /* set color black */ fprintf (fout, " 0 setgray\n"); fprintf (fout, " DescFont setfont\n"); if (*header.recordingdate) if (header.recordingtime!= NULL) fprintf (fout, " %d %d d ptc\n",MMTOXRES (secs* mm_per_sec)/2+ x,ytext); else fprintf (fout, " %d %d d ptc\n",MMTOXRES (secs* mm_per_sec)/2+ x,ytext); /* Print patient name */ if (*header.patientname) fprintf (fout, " %d %d (%s) ptr\n", MMTOXRES (maxx- borderx), ytext, conv (header.patientname)); /* Page */ fprintf (fout, " %d %d p ptr\n", MMTOXRES (maxx- borderx), ytext- (int) (DESCHEIGHT/72.0*25.4*YUNIT* 1.2)); fprintf (fout, " /tabur %d p stringwidth pop cmx add sub def\n", MMTOXRES (maxx- borderx)); /* Print institution */ if (*header.institution) fprintf (fout, " %d %d (%s) pt\n",x , ytext, conv (header.institution)); /* Time */ fprintf (fout, " TimeFont setfont\n" " /tabul 0 def\n" " 0 2 ary length 1 sub\n" " {\n" " /i exch def\n" " ymin ymax ary i get ary i 1 add get st\n" " } for\n"); /* print electrode names */ fprintf (fout, " ChannelFont setfont\n"); fprintf (fout, " %d %d [", x+ MMTOXRES (10), x+ MMTOXRES (secs* mm_per_sec- 20)); /* print electrode names */ for (i= 0; i< nelectrodes; ++i) fprintf (fout, "(%s) ", conv (header.electrode_name [i])); fprintf (fout, "] sc\n"); /* set color black */ fprintf (fout, " 0 setgray\n"); fprintf (fout, "} def\n\n"); fprintf (fout, "%%%%EndProlog\n"); fprintf (fout, "%%%%BeginSetup\n"); fprintf (fout, "%%%%IncludeResource: font Courier\n"); fprintf (fout, "%%%%IncludeResource: font Helvetica\n"); fprintf (fout, "%%%%IncludeResource: font Helvetica-Bold\n"); /* set fonts */ chanheight= CHANNELHEIGHT; if (height< (CHANNELHEIGHT/72.0*25.4* YUNIT* 1.2)) chanheight= (height*72)/(25.4*YUNIT); fprintf(fout, "%% set fonts\n" "/DescFont /Helvetica-ISO findfont [%d 0 0 %d 0 0] makefont def\n" "/TimeFont /Helvetica-ISO findfont [%d 0 0 %d 0 0] makefont def\n" "/ChannelFont /Helvetica-ISO findfont [%d 0 0 %d 0 0] " "makefont def\n", MMTOXRES (DESCHEIGHT/72.0*25.4), (int)(DESCHEIGHT/72.0*25.4*YUNIT), MMTOXRES (TIMEHEIGHT/72.0*25.4), (int)(TIMEHEIGHT/72.0*25.4*YUNIT), MMTOXRES (chanheight/72.0*25.4), (int)(chanheight/72.0*25.4*YUNIT)); fprintf (fout, "/cm %d def\n", MMTOPOINTS (10)); fprintf (fout, "/height %d def\n", (int) (NORMALHEIGHT*1.2)); fprintf (fout, "/cmx %d def\n", MMTOXRES (10)); fprintf (fout, "/mmy %d def\n", YUNIT); fprintf (fout, "/xmin %d def\n", x); fprintf (fout, "/topy %d def\n", (int) ((maxy- bordery- yoffset)*YUNIT- height/2)); fprintf (fout, "/hy %f def\n", height); fprintf (fout, "/f 250 string def\n", height); fprintf (fout, "/offset %d def\n", 4400+ 33*94+ 33); fprintf (fout, "/zerolines %d def\n", zerolines); fprintf (fout, "/xmax %d def\n", MMTOXRES (maxx- borderx)); fprintf (fout, "%%%%EndSetup\n"); /* Print title page */ if (showtitle) PrintTitle (fout); /* Init Scalings */ for (j= 0; j< pages; ++j) { fprintf (fout, "%%%%Page: %d %d\n", j+ 1, page++); from= start+ j* secs* header.sample_rate; if (from+ samples_per_screen> header.samples_per_channel) { per_page= (header.samples_per_channel-from)/ xscale; secs= ceil ((double) ((header.samples_per_channel-from)/ header.sample_rate)); if (secs< 2) secs=2; /* at least one timestring has to be printed */ } fprintf (fout, "%%%%BeginPageSetup\n"); fprintf (fout, "save sp\n"); fprintf (fout, "%%%%EndPageSetup\n"); /* init page */ actsec++; /* print time */ fprintf (fout, "%d %d [", bordery* YUNIT, (maxy- bordery- yoffset)* YUNIT); for (i= 1; i< secs; ++i) { int xx= x+ MMTOXRES (mm_per_sec* i); fprintf (fout, " %d (%s)", xx, GetDate (actsec, onlytime)); actsec++; } /* Print recording date */ if (*header.recordingdate) if (header.recordingtime!= NULL) string= GetDate (actsec+ (time_t) 1, onlydate); else string= header.recordingdate; else string= &header.null; fprintf (fout, "] (%s) (%d) ip\n", string, j+1); /* print curves */ /* for (i= 0; i< nelectrodes; ++i) { y= (maxy- bordery- yoffset)* YUNIT- height/2- i* height; GetLine (from, electrode [i], xscale, per_page, buf) ; PrintLine (fout, x, y,header.electrode_scale [electrode [i]]* YUNIT* 10/ electrodescale [electrode[i]].scale, per_page, buf); } */ fprintf (fout, "%%%%BeginData %d ASCII Lines\n", nelectrodes* ((per_page+119)/120)+1); fprintf (fout, "%d %d dc2\n", nelectrodes, (per_page+119)/120); for (i= 0; i< nelectrodes; ++i) { GetLine (from, electrode [i], xscale, per_page, buf) ; PrintLine2 (fout, header.electrode_scale [electrode [i]]* YUNIT* 10/ electrodescale [electrode[i]].scale, per_page, buf); } fprintf (fout, "%%%%EndData\n"); fprintf (fout, "%%%%PageTrailer\n"); /* print this page */ fprintf (fout, "restore showpage\n"); } /* Write Trailer */ fprintf (fout, "%%%%Trailer\n"); fprintf (fout, "%%%%EOF\n"); if (fout!= stdout) fclose (fout); ebs_close (header.ebs_file); }