	Aufbau einer UV-Datei
	*********************

"UVOD2   "	Die ersten 8 Bytes bestimmen das Format
"Kommentar\n"	Der Kommentarstring wird durch ein 0-Byte abgeschlossen

struct uv_kopf
{       LONG    start,ende,delta,slit;   /* Werte in PicoMeter (0.001nm) */
        WORD    period;   /* Daempfung in Millisekunden */
        WORD    multi;    /* Anzahl Multiscans, Daten aber bereits dividiert */
        LONG    conz;     /* Konzentration * Schichtdicke in NanoMol/l*cm    */
        LONG    yfaktor;  /* Die y-Werte sind um diesen Faktor vergroessert  */
} kopf;

LONG y1,y2....yn;	// n = (start-ende)/delta + 1
	um Platz zu sparen ist wenn moeglich jeweils die
	Differenzen zum vorherigen y-Wert gespeichert (siehe gepacktlesen())

LONG ist jeweils 4 Bytes und WORD 2 Bytes lang. Sie werden mit MSB-first
gespeichert, also signifikanteste Bytes zuerst.


Programmauszug um Datei zu lesen:
*********************************

int gepacktlesen(FILE *fp,LONG *y)
{
 /* Wenn erstes Bit gesetzt (c & 0x80 == 0x80), dann sind die restlichen 7 Bits
    die Differenz zum vorherigen Wert.
    Wenn das erste Bit nicht, aber das 2.Bit gesetzt ist (c & 0xC0 == 0x40),
    dann sind die restlichen 6 Bits + das naechste Byte die Differenz zum
    vorherigen Wert.
    Wenn weder das erste noch das 2. Bit gesetzt sind (c & 0xC0 == 0), dann
    sind die restlichen 6 Bits + die naechsten 3 Bytes ein absoluter Wert.
 */
 static long letzterwert=0;
 long dy;
 int c,c2,c3,c4;
 if((c=getc(fp))==EOF) {*y=0; return EOF;}
 if(c & 0x80)
        {dy=c & 0x7F; if(dy & 0x40) dy |= 0xFFFFFF80;
         *y=letzterwert+=dy;
        }
 else if(c & 0x40)
        {c2=getc(fp);
         dy=((c & 0x3F)<<8)+c2; if(dy & 0x2000) dy |= 0xFFFFC000;
         *y=letzterwert+=dy; c=c2;
        }
 else
        {c2=getc(fp); c3=getc(fp); c4=getc(fp);
         dy=(c<<24)+(c2<<16)+(c3<<8)+c4; if(dy & 0x20000000) dy |= 0xC0000000;
         *y=letzterwert=dy; c=c4;
        }
 return c;
}

int wordlesen(FILE *fp)
{
 int c1,c2; WORD x;
 c1=getc(fp); c2=getc(fp);
 x=(c1<<8)+c2;
 return x;
}

LONG longlesen(FILE *fp)
{
 LONG c1,c2,c3,c4,x;
 c1=getc(fp); c2=getc(fp); c3=getc(fp); c4=getc(fp);
 x=(c1<<24)+(c2<<16)+(c3<<8)+c4;
 return x;
}


static struct uv_kopf kopf;

void einleseprogramm(float *yfeld)  //gekuerzt
{
 FILE *fp;
 char format[10],*s;
 int i,c;
 LONG x,y,j;
 float start,ende,*py;
 fp=fopen(filename,"r");
 for(i=0;i<8;i++) format[i]=getc(fp);
 format[8]=0;
 if(strcmp(format,"UVOD2   ")==0)
        {uvformat=UVOD2;
         for(s=substanzname;(c=getc(fp))>=' ';)  *s++ = c;
         *s=0;
         kopf.start=longlesen(fp); kopf.ende=longlesen(fp);
         kopf.delta=longlesen(fp); kopf.slit=longlesen(fp);
         kopf.period=wordlesen(fp); kopf.multi=wordlesen(fp);
         kopf.conz=longlesen(fp); konz=kopf.conz/1e9;
         kopf.yfaktor=longlesen(fp); yfakt=(double)kopf.yfaktor;
         start=kopf.start/1e3; ende=kopf.ende/1e3; //Umrechnung in nm
         npkt=(kopf.start-kopf.ende)/kopf.delta+1; //Anzahl y-Werte
         for(py=yfeld,x=kopf.start; x>=kopf.ende; x-=kopf.delta,py++)
           {if(gepacktlesen(fp,&y)==EOF) printf("Fehler in UV-Datei\n");
            *py=mody_umrechnung(y/yfakt,*mody,konz);
	   }
	}
 else printf("unbekanntes Format\n");
}


Programmauszug um Datei zu speichern:
*************************************
static int packflag=0;

void spektrum_speichern(char *filename,float *yfeld,WORD *mody,WORD *irev,
                   char *snam, struct uv_kopf *kopf)
{
 LONG x,y,j,i,npkt;
 FILE *fp;
 double yfak,konz;
 fp=fopen(filename,WRITE);
 if(fp==NULL) {printf("Fehler beim oeffnen von '%s'\n",filename); exit(0);}
 fprintf(fp,"UVOD2   "); /* Dateiformat = UV Optische Dichte Version 2 */
 fprintf(fp,"%s\n",snam);
 longspeichern(fp,kopf->start); longspeichern(fp,kopf->ende);
 longspeichern(fp,kopf->delta); longspeichern(fp,kopf->slit);
 intspeichern(fp,kopf->period); intspeichern(fp,kopf->multi);
 longspeichern(fp,kopf->conz);  longspeichern(fp,kopf->yfaktor);
 yfak=(double)kopf->yfaktor; konz=(double)kopf->conz;
 npkt=(kopf->start-kopf->ende)/kopf->delta+1;
 packflag=0;
 for(i=0,x=kopf->start; x>=kopf->ende; x-=kopf->delta,i++)
        {if(*irev==0) j=npkt-1-i; else j=i;
         switch(*mody)
          {case OD:         y=idfix(yfeld[j]*yfak);
           CASE EPSILON:    y=idfix(yfeld[j]*yfak*konz);
           CASE LOGEPSILON: y=idfix(pow(10.,yfeld[j])*yfak*konz);
           CASE TRANSMISSION:y=idfix(-Log10a(yfeld[j]/100.)*yfak);
           DEFAULT: printf("unbekanntes mody=%d\n",mody);
          }
         gepacktspeichern(fp,y);
        }
 fclose(fp);
 return;
}

void intspeichern(FILE *fp,int y) {putc(y>>8,fp);  putc(y,fp);}
void longspeichern(FILE *fp,LONG y)
{
 putc((int)(y>>24),fp); putc((int)(y>>16),fp);
 putc((int)(y>>8),fp);  putc((int)(y),fp);
}
void gepacktspeichern(FILE *fp,LONG y)
{
 static LONG letzterwert=0; LONG dy;
 dy=y-letzterwert;
 if(packflag==0 || dy>0x1FFF || dy<(-0x2000))
        {putc((int)((y>>24)&0x3F),fp); putc((int)(y>>16),fp);
         putc((int)(y>>8),fp);  putc((int)(y),fp);
        }
 else if(dy>0x3F || dy<(-0x40))
        {putc((int)((dy>>8)&0x3F)+0x40,fp); putc((int)(dy),fp);}
 else   putc((int)(dy&0x7F)+0x80,fp);
 letzterwert=y; packflag=1;
}


	Aufbau einer SPEX-Datei
	***********************

"SPEX2   "		Die ersten 8 Bytes bestimmen das Format
BYTE nr; char *text;	Diverse Parameter des Spektrums
....
BYTE 0xFF;		Abschluss des Parameter-Teils

LONG y1,y2....yn;	// n = (start-ende)/delta + 1
	um Platz zu sparen ist wenn moeglich jeweils die
	Differenzen zum vorherigen y-Wert gespeichert (siehe gepacktlesen())

Die Bedeutung der Parameter ist durch nr definiert und kann ueber folgende
Tabelle ermittelt werden:

typedef char string40[40];
static string40 ptext[30] =
 {		   //		Beispiele:
  "PROGRAMM.....", //nr=0	OLGA/MOPS
  "FILENAME.....", //		test.spex
  "SUBSTANCE....",
  "DATE.........",
  "OPERATOR.....",
  "EXLINE.....AU",
  "SOLVENT......",
  "TEMP........K",
  "CONC.........",
  "OPT.DENSITY..",
  "POLARISER.DGR", //nr=10
  "ANALYSER..DGR",
  "CHOPPER...RPS",
  "EX-FILTER..NM",
  "EM-FILTER..NM",
  "EX-SLITS...MM", //		2.5 (= +-5nm)
  "EM-SLITS...MM", //		0.5/0.5
  "PM-VOLT.....V", //		1400
  "SAMPLE-CELL..", //		Gas-Zelle
  "REMARKS......",
  "START.SCAN...", //nr=20	600 nm
  "END.SCAN.....",		400 nm
  "STEP.........",		0.5 nm
  "SPECTRUM-TYPE", //		Emission/Excitation/Absorption
  "NO.SCANS.....", //		1
  "YDATA........", //		COUNTS/CPS/OD
  "REP.NUMBER...",
  "REP.TIME....S",
  "MES.TIME....S", //		2.5
  "LASERMODUS..."}; //nr=29

Beim Aufnehmen eines Spektrums sollten DATE und YDATA automatisch
richtig gesetzt werden.
YDATA wird noch mit einem Faktor ergaenzt, durch den man dividieren muss um
die richtigen y-Werte zu erhalten. Oder anders ausgedrueckt:
die y-Werte wurden vom Messprogramm mit diesem Faktor multipliziert um
Integer-Werte im zulaessigen Bereich zu erhalten.

In "MES.TIME....S" (nr=28) steht die Zeit in Sekunden als Fliesszahl.
Im uvshow-Programm wird in kopf.period in Millisekunden als 16-Bit-Ganzzahl
gespeichert. Deshalb wird bei mehr als 32.767 auf ganze Sekunden gerundet
und zur Kennzeichnung als negative Zahl in kopf.period gespeichert.
