Exemple #1
0
HArc *CreateArc(MemHeap *mem, Lattice *lat, LArc *la, int start_time, int pos, int arcId, HArc *lastArc, float insPen, float lmScale, HMMSet *hset, ArcInfo *aInfo){ /*Creates an arc.*/
   MLink macroName;
   LNode *ln;
   ArcList *al;
   HArc *ans = (HArc*)New(mem, sizeof(HArc)), *arc;
   /*First create the arc.*/
   ans->id = arcId;
   ans->pos = pos;
   ans->parentLarc = la;
   ans->t_start = start_time + 1;
   ans->t_end   = start_time + TimeToNFrames((float)la->lAlign[pos].dur, aInfo);
   ans->mpe = NULL;

   if(ans->t_end < start_time) HError (1, "Error- bad times in lattice");

   ans->follTrans = ans->precTrans = NULL;
   ans->phone = la->lAlign[pos].label; /*The phone in context.*/
   if(pos==0) ans->word = la->end->word->wordName;
   else ans->word = NULL;

   if((macroName=FindMacroName(hset,'l',ans->phone))==NULL)
      HError(2321,"CreateArc: Unknown align label %s",ans->phone->name); 
   ans->hmm = (HLink)macroName->structure;  /* Note-- "hmm" has to be set at this stage because HMM addresses are compared for purposes of
                                               sorting arcs and setting the calcArc field later to decide which ones need to have
                                               forward-backward done. */
   ans->calcArc = NULL;
  
   /*Next add the to- transitions (if there are any.)*/
   ln=la->start;
   if(pos==0) /*First phone of the word-- add connecting arcs to the last phones of preceding words.*/
      for(al=(ArcList*)ln->hook;al;al=al->t){
         arc = al->h; 
         AddArcTrans(mem, arc, ans, la->prlike*lat->prscale + la->lmlike*lmScale + insPen);
         if(ans->t_start != arc->t_end+1) HError(1, "CreateArc: mismatched times.");
      }
   else{ /*Add the transition between this and the previous phone. */
      AddArcTrans(mem, lastArc, ans, 0);
      if(ans->t_end < lastArc->t_end)  HError(1, "Times don't match in lattice.");
   }    

   /*Now for the from-transitions...*/
   /*All we need to do is annotate the ending LNode with this arc.
     Any necessary transitions will be added later. */
   ln = la->end;
   if(pos==la->nAlign-1)/*if at end of word,*/
      ln->hook = (ArcList*) ConsArcList(&tempArcStack, ans, (ArcList*)ln->hook); 
   /* create from temporary memory,  freed when ArcFromLat finishes. */
  
   return ans;
}
Exemple #2
0
/* EXPORT->LoadStatsFile: load the statistics file output by HERest */
void LoadStatsFile(char *statfile,HMMSet *hset,Boolean otrace)
{
   Source src;
   char hname[256];
   int i,idx,count,N,lnum = 0;
   float x;
   HMMDef *hmm;
   MLink ml;
   LabId hmmId;
   double occSum = 0.0;
   long occN = 0;
   StateInfo *si;
   Boolean bin=FALSE;

   if(InitSource(statfile,&src,NoFilter)<SUCCESS)
      HError(7210,"LoadStatsFile: Can't open file %s", statfile);
   while(ReadInt(&src,&idx,1,bin)) {
      ++lnum;
      if (!ReadString(&src,hname) || !ReadInt(&src,&count,1,bin))
         HError(7250,"LoadStatsFile: Format error in file %s line %d",
                statfile,lnum);

      /* look up hname and find num states N */
      if ((hmmId = GetLabId(hname,FALSE))==NULL)
         HError(7251,"LoadStatsFile: unknown name %s at line %d",
                hname,lnum);
      if ((ml = FindMacroName(hset,'l',hmmId))==NULL)
         HError(7251,"LoadStatsFile: unknown model %s at line %d",
                hname,lnum);
      hmm = (HMMDef *) ml->structure;
      N = hmm->numStates;
      for (i=2; i<N; i++) {
         if (!ReadFloat(&src,&x,1,bin))
            HError(7250,"LoadStatsFile: Float format error file %s line %d\n",
                   statfile,lnum);
         si = hmm->svec[i].info;
         si->stateCounter = count;/* load the # of times the state occurred */
         memcpy(&(si->hook),&x,sizeof(float)); /* !! */
         occSum += x; ++occN;
      }
   }
   CloseSource(&src);
   if (otrace || (trace & T_OCC)) {
      printf("  Stats loaded for %d models\n",lnum);
      printf("  Mean Occupation Count = %f\n",occSum/occN);
      fflush(stdout);
   }
}
Exemple #3
0
/* Initialise: load hmm and initialise global data structures */
void Initialise(void)
{
   LabId  hmmId;
   char base[MAXSTRLEN];
   char path[MAXSTRLEN];
   char ext[MAXSTRLEN]; 
   int s;  

   /* Stacks for global structures requiring memory allocation */
   CreateHeap(&segmentStack,"SegStore", MSTAK, 1, 0.0, 100000, LONG_MAX);
   CreateHeap(&sequenceStack,"SeqStore", MSTAK, 1, 0.0, 10000, 10000);
   CreateHeap(&clustSetStack,"ClustSetStore", MSTAK, 1, 0.0, 1000, 1000);
   CreateHeap(&transStack,"TransStore", MSTAK, 1, 0.0, 1000, 1000);
   CreateHeap(&traceBackStack,"TraceBackStore", MSTAK, 1, 0.0, 1000, 1000);
   CreateHeap(&bufferStack,"BufferStore", MSTAK, 1, 0.0, 1000, 1000);
   CreateHeap(&msdinfoStack,"MSDInfoStore", MSTAK, 1, 0.0, 1000, 1000);

   /* Load HMM def */
   if(MakeOneHMM( &hset, BaseOf(hmmfn,base))<SUCCESS)
      HError(2128,"Initialise: MakeOneHMM failed");
   if(LoadHMMSet( &hset,PathOf(hmmfn,path),ExtnOf(hmmfn,ext))<SUCCESS)
      HError(2128,"Initialise: LoadHMMSet failed");
   SetParmHMMSet(&hset);
   if ((hset.hsKind==DISCRETEHS)||(hset.hsKind==TIEDHS))
      uFlags = (UPDSet) (uFlags & (~(UPMEANS|UPVARS)));
   AttachAccs(&hset, &gstack, uFlags);

   /* Get a pointer to the physical HMM and set related globals */
   hmmId = GetLabId(base,FALSE);   
   macroLink = FindMacroName(&hset,'h',hmmId);
   hmmLink = (HLink)macroLink->structure; 
   nStates = hmmLink->numStates;
   nStreams = hset.swidth[0];
   for(s=1; s<=nStreams; s++)
      maxMixInS[s] = MaxMixInS(hmmLink, s);
   msdInfo = CreateMSDInfo(&msdinfoStack, hmmLink);

   SetVFloor( &hset, vFloor, minVar);

   if(segLab != NULL)
      segId = GetLabId(segLab,TRUE);
   if(trace>0)
      PrintInitialInfo();

   thisP = CreateVector(&gstack,nStates);
   lastP = CreateVector(&gstack,nStates);
}
Exemple #4
0
/* PHIdent: parse a hmm ident and do pattern match */
static void PHIdent(ILink *models, HMMSet *hset)
{
   char pattern[MAXSTRLEN];
   int h;
   MLink q;
   LabId hmmId;
   Boolean fullName=TRUE; /* are there wildcards in the name */
   char *p;

   SkipSpaces();
   GetAlpha(pattern);
   p = pattern; h=0;
   while ((*p != '\0') && (h<MAXSTRLEN) && (fullName)) {
     if ((*p=='*')||(*p=='?')||(*p=='%')) fullName=FALSE;
     h++;
     p = pattern+h;
   }
   if (fullName) { /* this is the name of the model */
      hmmId = GetLabId(pattern,FALSE);
      q = FindMacroName(hset,'l',hmmId);
      if (q != NULL) {
         if (trace & T_ITM)
            printf("%s ",hmmId->name);
         AddItem((HLink) q->structure, q->structure, models);
      }
   } else { /* need to search for all models that match */
     for (h=0; h<MACHASHSIZE; h++)
       for (q=hset->mtab[h]; q!=NULL; q=q->next)
         if (((q->type=='h') && (parsePhysicalHMM)) || ((q->type=='l') && (!parsePhysicalHMM))) {
	   if (DoMatch(q->id->name,pattern)) {
	     if (trace & T_ITM)
	       printf("%s ",q->id->name);
	     AddItem((HLink) q->structure, q->structure, models);
	   }
         }
   }
}
Exemple #5
0
/* InitStats: Create and init all necessary global accumulators */
void InitStats(char *listFn)
{
   int h,p,l;
   MLink q,hm;
   HLink hmm;
   HMMSet *hset;

   CreateHeap(&tmpHeap,"TempHeap",MSTAK,1,1.0,8000,80000);
   CreateHeap(&statHeap,"StatHeap",MSTAK,1,1.0,8000,240000);

   hset=(HMMSet*)New(&tmpHeap,sizeof(HMMSet));
   CreateHMMSet(hset,&tmpHeap,FALSE);
   if(MakeHMMSet(hset,listFn)<SUCCESS)
      HError(1328,"Initstats: MakeHMMSet failed");

   /* Make sure we have entries for ENTER / EXIT labels */
   if (FindMacroName(hset,'l',enterId)==NULL) {
      hmm=(HMMDef*)New(&tmpHeap,sizeof(HMMDef));
      NewMacro(hset,0,'l',enterId,hmm);
      NewMacro(hset,0,'h',enterId,hmm);
   }
   if (FindMacroName(hset,'l',exitId)==NULL) {
      hmm=(HMMDef*)New(&tmpHeap,sizeof(HMMDef));
      NewMacro(hset,0,'l',exitId,hmm);
      NewMacro(hset,0,'h',exitId,hmm);
   }

   pSize=hset->numPhyHMM;
   pTab=(Cntr*)New(&statHeap,(pSize+1)*sizeof(Cntr));
   
   p=1;
   pTab[0].name=nullId;
   for (h=0; h<MACHASHSIZE; h++)
      for (q=hset->mtab[h]; q!=NULL; q=q->next) {
         if (q->type=='h') {
            hmm=(HLink) q->structure;
            hmm->hook=(Ptr)p;
            pTab[p].name=q->id;
            pTab[p].count=0;
            p++;
         }
      }

   lSize=hset->numLogHMM;
   lTab=(WordInfo*)New(&statHeap,(lSize+1)*sizeof(WordInfo));

   l=1;
   InitWordInfo(lTab,nullId,pTab);
   for (h=0; h<MACHASHSIZE; h++)
      for (q=hset->mtab[h]; q!=NULL; q=q->next)
         if (q->type=='l') {
            hmm=(HLink) q->structure;
            hm=FindMacroStruct(hset,'h',q->structure);
            if (hm==NULL || hmm->hook==0)
               HError(1390,"InitStats: No physical name found for %s",
                      q->id->name);
            InitWordInfo(lTab+l,q->id,pTab+(int)hmm->hook);
            l++;
         }
   qsort(lTab+1,lSize,sizeof(WordInfo),wd_cmp);
   for (l=1; l<=lSize; l++)
      lTab[l].name->aux=(Ptr)l;
   Dispose(&tmpHeap,hset);

   if (doBigram) {   /* create aetab */
      aetabsize=hashsizes[hSize];
      aetab=(AEntry**)New(&statHeap,aetabsize*sizeof(AEntry*));
      for (l=0;l<aetabsize;l++) aetab[l]=NULL;
   }
   if (trace&T_BAS) {
      PrintSettings();
      printf("\n\nRead Label list - %d/%d labels\n",lSize,pSize);
   }
}
Exemple #6
0
void ArcFromLat(ArcInfo *aInfo, HMMSet *hset){
   Lattice *lat;
   int larcid,seg;
   int start_time;
   HArc *arc;
   int l;
   float framedur;

   if(!StackInitialised)
      CreateHeap(&tempArcStack,    "tempArcStore",       MSTAK, 1, 0.5, 1000,  10000);

   aInfo->start=aInfo->end=0;
   aInfo->nArcs=0;
   if(IsLMScale)
      aInfo->lmScale = LMSCALE;
   else /* If none is specified use the one from the lattice. */
      aInfo->lmScale = aInfo->lat[0]->lmscale;
  
   /* Lattices actually never specify frame duration.  Usual source is config, FRAMEDUR. */
   /* if(lat->framedur != 0) framedur = lat->framedur / 10000000;   */
   if (FRAMEDUR) framedur = FRAMEDUR; /* config. */
   else framedur = 0.01;
   aInfo->framedur = framedur;

   if(!IsWdPen)
      aInfo->insPen = aInfo->lat[0]->wdpenalty;
   else aInfo->insPen = WDPEN;

   /*  Add all the arcs in the lattice into the Arc structure. */
   for(l=0;l<aInfo->nLats;l++) /* this handles multiple lattices so e.g. the correct lattice can be added to the recognition lattice
                                  in case it happens to be absent. */
      {
         lat = aInfo->lat[l];
         ZeroHooks(lat);
         FixLatTimes(lat); /* this can be deleted at some point. */
         for(larcid=0;larcid<lat->na;larcid++){
            start_time = TimeToNFrames(lat->larcs[larcid].start->time, aInfo);
      
            for(seg=0;seg<lat->larcs[larcid].nAlign;seg++){
               arc = CreateArc(aInfo->mem, lat, lat->larcs+larcid, start_time, seg, ++aInfo->nArcs, (seg==0?NULL:aInfo->end), aInfo->insPen, aInfo->lmScale, hset, aInfo);
               /* this creates the phone arc and also the transitions between them. (confusingly, phone 
                  arcs are actually nodes in the datastructure used here, and transitions are arcs)  */
	
               /*Insert into the linked list of arcs:*/
               if(!aInfo->start)  aInfo->start=arc;
               arc->prec = aInfo->end;
               arc->foll = NULL;
               if(aInfo->end) aInfo->end->foll = arc;
               aInfo->end = arc;
               start_time = aInfo->end->t_end;
            }
         }
      }
  

   SortArcs(aInfo);  /* Sort the arcs in order of start & end time
                        [ & in such a way that ones with identical HMMs are adjacent.] */

   if(BackTransitions(aInfo)){ /* A check-- should never be true if properly sorted */
      HError(1, "Error: file %s: back transitions exist.\n", (aInfo->lat[0]->utterance?aInfo->lat[0]->utterance:"[unknown]"));
   }


   /* Pool sets of identical models with identical start & end times. */
   for(arc=aInfo->start; arc; arc=arc->foll){
      HArc *arc2;
      if((arc2=arc->prec) != NULL && arc2->t_end==arc->t_end && arc2->t_start==arc->t_start && arc2->hmm==arc->hmm){
         if(arc2->calcArc == NULL) arc->calcArc = arc2;
         else arc->calcArc = arc2->calcArc;
      }
   }


   {  /*  Set up the structures which relate to the computation of model likelihoods. */
      int q=0,Q; MLink macroName;
      int T=0,t;
      for(arc=aInfo->start;arc;arc=arc->foll){
         if(arc->calcArc) arc->id = GHOST_ARC;
         else{ arc->id = ++q; }
         T=MAX(T,arc->t_end);
      }
      aInfo->Q = Q = q; /* num unique arcs. */
      aInfo->T = T; 
      aInfo->ac = (Acoustic*)New(aInfo->mem, sizeof(Acoustic) * (q+1)); 
      q=0;
      for(arc=aInfo->start;arc;arc=arc->foll){
         if(!arc->calcArc){  /* if this is one of the 'calculated' arcs */
            Acoustic *ac = arc->ac = aInfo->ac + ++q;

            ac->myArc=arc;
            ac->t_start=arc->t_start; ac->t_end=arc->t_end;
	
            if((macroName=FindMacroName(hset,'l',arc->phone))==NULL)
               HError(2321,"CreateArc: Unknown align label %s",arc->phone->name); 
            ac->hmm = (HLink)macroName->structure;  

            ac->Nq = ac->hmm->numStates; /* could be either HMM, same structure. */
            if(ac->t_start == ac->t_end+1){ 
               ac->SP=TRUE; 
               ac->alphat=ac->alphat1=NULL;ac->betaPlus=NULL;ac->otprob=NULL;
            } else {
               int j,s,SS,S = hset->swidth[0]; /* probably just 1. */
	       StreamElem *ste;

	       SS=(S==1)?1:S+1;
               ac->SP=FALSE;
               ac->alphat = CreateDVector(aInfo->mem, ac->Nq);
               ac->alphat1 = CreateDVector(aInfo->mem, ac->Nq);
               ac->betaPlus = ((DVector*)New(aInfo->mem, sizeof(DVector)*(ac->t_end-ac->t_start+1)))-ac->t_start;
               ac->otprob = ((float****)New(aInfo->mem, sizeof(float***)*(ac->t_end-ac->t_start+1)))-ac->t_start;
               for(t=ac->t_start;t<=ac->t_end;t++){
                  ac->betaPlus[t] = CreateDVector(aInfo->mem,ac->Nq);
		  ac->otprob[t] = ((float***)New(aInfo->mem,(ac->Nq-2)*sizeof(float **)))-2;
		  for(j=2;j<ac->Nq;j++){
                     ac->otprob[t][j] = (float**)New(aInfo->mem,SS*sizeof(float*)); /*2..Nq-1*/
		     ste = ac->hmm->svec[j].info->pdf+1;
		     if (S==1) {
		        ac->otprob[t][j][0] = NULL;
		     } else {
		        ac->otprob[t][j][0] = (float*)New(aInfo->mem,sizeof(float));
			ac->otprob[t][j][0][0] = LZERO;
			for (s=1;s<=S;s++,ste++)
			  ac->otprob[t][j][s] = NULL;
		     }
                  }
               }	
            }
         }
      }
      for(arc=aInfo->start;arc;arc=arc->foll)  if(arc->calcArc) arc->ac = arc->calcArc->ac;


      /* Set up arrays qLo[t] and qHi[t] which are used to speed up iterations over q. */
    
      aInfo->qLo = (int*)New(aInfo->mem, sizeof(int)*(aInfo->T+1));  /* For efficiency later, work out min & max q active at each time t. */
      aInfo->qHi = (int*)New(aInfo->mem, sizeof(int)*(aInfo->T+1));
      for(t=1;t<=T;t++){  aInfo->qLo[t] = T+1; aInfo->qHi[t] = -1;  }
      for(q=1;q<=Q;q++){
         for(t=aInfo->ac[q].t_start;t<=MAX(aInfo->ac[q].t_end,aInfo->ac[q].t_start);t++){ 
            /* the MAX above is to handle tee models, so they will be in beam at t==t_start. */
            aInfo->qLo[t] = MIN(aInfo->qLo[t], q);
            aInfo->qHi[t] = MAX(aInfo->qHi[t], q);
         }
      } 
   }

   if(trace&T_ARC && debug++ < 100){
      printf("[HArc:] %d arcs, depth %f, depth[reduced] %f\n", aInfo->nArcs, Depth(aInfo,TRUE), Depth(aInfo,FALSE));
      if(trace&T_ARC2)
         PrintArcs(stdout, aInfo->start);
   }
  
   ResetHeap(&tempArcStack);
}
/* Initialise: load HMMs and create accumulators */
static void Initialise(void)
{
   int s,V;
   Boolean eSep;
   char base[MAXSTRLEN];
   char path[MAXSTRLEN];
   char ext[MAXSTRLEN];

   /* Load HMM defs */     
   if(MakeOneHMM(&hset,BaseOf(hmmfn,base))<SUCCESS)
      HError(2028,"Initialise: MakeOneHMM failed");
   if(LoadHMMSet(&hset,PathOf(hmmfn,path),ExtnOf(hmmfn,ext))<SUCCESS)
      HError(2028,"Initialise: LoadHMMSet failed");
   SetParmHMMSet(&hset);
   if (hset.hsKind==DISCRETEHS || hset.hsKind==TIEDHS)
      HError(2030,"Initialise: HCompV only uses continuous models");

   /* Create a heap to store the input data */
   /*CreateHeap(&iStack,"InBuf", MSTAK, 1, 0.5, 100000, LONG_MAX);*/
   
   /* Get a pointer to the physical HMM */
   hmmId = GetLabId(base,FALSE);
   macroLink = FindMacroName(&hset,'h',hmmId);
   if (macroLink==NULL)
      HError(2020,"Initialise: cannot find hmm %s in hset",hmmfn);
   hmmLink = (HLink)macroLink->structure;

   /* Find out for which streams full covariance is needed */
   CheckVarianceKind( );

   /* Create accumulators for the mean and variance */
   for (s=1;s<=hset.swidth[0]; s++){
      V = hset.swidth[s];
      accs[s].meanSum=CreateVector(&gstack,V);
      ZeroVector(accs[s].meanSum);
      if (fullcNeeded[s]) {
         accs[s].squareSum.inv=CreateSTriMat(&gstack,V);
         accs[s].fixed.inv=CreateSTriMat(&gstack,V);
         ZeroTriMat(accs[s].squareSum.inv);
      }
      else {
         accs[s].squareSum.var=CreateSVector(&gstack,V);
         accs[s].fixed.var=CreateSVector(&gstack,V);
         ZeroVector(accs[s].squareSum.var);
      }
   }

   /* Create an object to hold the input parameters */
   SetStreamWidths(hset.pkind,hset.vecSize,hset.swidth,&eSep);
   obs=MakeObservation(&gstack,hset.swidth,hset.pkind,FALSE,eSep);
   if(segLab != NULL) {
      segId = GetLabId(segLab,TRUE);
   }

   if (trace&T_TOP) {
      printf("Calculating Fixed Variance\n");
      printf("  HMM Prototype: %s\n",hmmfn);
      printf("  Segment Label: %s\n",(segLab==NULL)?"None":segLab);
      printf("  Num Streams  : %d\n",hset.swidth[0]);
      printf("  UpdatingMeans: %s\n",(meanUpdate)?"Yes":"No");
      printf("  Target Direct: %s\n",(outDir==NULL)?"Current":outDir);     
   }
}
Exemple #8
0
BOOL MacrosCallback(HWND hDlg, UINT uMsg, WPARAM wPar, LPARAM lPar)
{	HWND  ListBox;
	CHAR  Buf[256];
	PMAP  ThisMapping, m, *MapPtr;
	INT	  i, k;

	PARAM_NOT_USED(lPar);
	switch (uMsg) {
		case WM_INITDIALOG:
			FreeMappings(NewMappings);
			NewMappings = NULL;
			ListBox = GetDlgItem(hDlg, IDC_MACROLIST);
			if (ListBox) {
				MapPtr = &NewMappings;
				SendMessage(ListBox, LB_RESETCONTENT, 0, 0);
				for (m = FirstMapping; m != NULL; m = m->Next) {
					if ((ThisMapping = DupMapping(m)) != NULL) {
						SendMessage(ListBox, LB_ADDSTRING, 0, (LPARAM)m->Name);
						*MapPtr = ThisMapping;
						MapPtr = &ThisMapping->Next;
					} else ErrorBox(MB_ICONSTOP, 300, 6);
				}
				SetDlgItemText(hDlg, IDC_MACRONAME,	   "");
				SetDlgItemText(hDlg, IDC_MACROINPUT,   "");
				SetDlgItemText(hDlg, IDC_MACROREPLACE, "");
				SendDlgItemMessage(hDlg, IDC_MACRONAME,    EM_LIMITTEXT,
								   sizeof(Buf)/2 - 1, 0);
				SendDlgItemMessage(hDlg, IDC_MACROINPUT,   EM_LIMITTEXT,
								   sizeof(Buf)   - 1, 0);
				SendDlgItemMessage(hDlg, IDC_MACROREPLACE, EM_LIMITTEXT,
								   sizeof(Buf)   - 1, 0);
				EnableWindow(GetDlgItem(hDlg, IDC_DELMACRO), FALSE);
			}
			CheckDlgButton(hDlg, IDC_INSERTMODE,  TRUE);
			CheckDlgButton(hDlg, IDC_COMMANDMODE, TRUE);
			CheckDlgButton(hDlg, IDC_COMMANDLINE, TRUE);
			CheckRadioButton(hDlg, IDC_MAP, IDC_ABBREV, IDC_MAP);
			break;

		case WM_COMMAND:
			ListBox = GetDlgItem(hDlg, IDC_MACROLIST);
			if (!ListBox) break;
			switch (COMMAND) {
				static BOOL InitialString = FALSE;
				
				case IDC_MACROLIST:
					if (NOTIFICATION != LBN_SELCHANGE) break;
					i = SendMessage(ListBox, LB_GETCURSEL, 0, 0);
					if (i == LB_ERR) m = NULL;
					else {
						SendMessage(ListBox, LB_GETTEXT, i, (LPARAM)(LPSTR)Buf);
						for (m = NewMappings;
							 m != NULL && lstrcmp(m->Name, Buf);
							 m = m->Next);
					}
					if (m != NULL) {
						InitialString = TRUE;
						SetDlgItemText(hDlg, IDC_MACRONAME, Buf);
						SetDlgItemText(hDlg, IDC_MACROINPUT, m->InputDisplay);
						SetDlgItemText(hDlg, IDC_MACROREPLACE, m->Replace);
						CheckRadioButton(hDlg, IDC_MAP, IDC_ABBREV,
										 m->Flags & M_ABBREVIATION
										 ? IDC_ABBREV : IDC_MAP);
						CheckDlgButton(hDlg, IDC_INSERTMODE,
									   (m->Flags & M_INSERTMODE) !=0);
						CheckDlgButton(hDlg, IDC_COMMANDMODE,
									   (m->Flags & M_COMMANDMODE)!=0);
						CheckDlgButton(hDlg, IDC_COMMANDLINE,
									   (m->Flags & M_COMMANDLINE)!=0);
						EnableWindow(GetDlgItem(hDlg, IDC_COMMANDMODE),
									 (m->Flags & M_ABBREVIATION) ==0);
						InitialString = FALSE;
					} else {
						/*should not occur, set empty name to indicate error*/
						SetDlgItemText(hDlg, IDC_MACRONAME, "");
					}
					EnableWindow(GetDlgItem(hDlg, IDC_DELMACRO),
								 m != NULL);
					DefaultOkButton(hDlg);
					break;

				case IDC_MACRONAME:
				case IDC_MACROINPUT:
					if (NOTIFICATION != EN_CHANGE) break;
					GetDlgItemText(hDlg, IDC_MACRONAME, Buf, sizeof(Buf));
					for (k = 0; k < 2; ++k) {
						LPWORD CmpMapping;
						DWORD  f;

						i = FindMacroName(ListBox, Buf);
						if (i != -1 || k) break;
						/*same name not found, try to find same input...*/
						GetDlgItemText(hDlg, IDC_MACROINPUT, Buf, sizeof(Buf));
						if (!TranslateMapping(&CmpMapping, Buf)) break;
						f = 0;
						if (IsDlgButtonChecked(hDlg, IDC_ABBREV))
							f |= M_ABBREVIATION;
						if (IsDlgButtonChecked(hDlg, IDC_INSERTMODE))
							f |= M_INSERTMODE;
						if (IsDlgButtonChecked(hDlg, IDC_COMMANDMODE))
							f |= M_COMMANDMODE;
						if (IsDlgButtonChecked(hDlg, IDC_COMMANDLINE))
							f |= M_COMMANDLINE;
						for (m = NewMappings; m != NULL; m = m->Next)
							if (IsMappingEqual(m->InputMatch, CmpMapping)
									&& (m->Flags & f) == m->Flags)
								break;
						_ffree(CmpMapping);
						if (m == NULL) break;
						lstrcpy(Buf, m->Name);
					}
					SendMessage(ListBox, LB_SETCURSEL, i, 0);
					EnableWindow(GetDlgItem(hDlg, IDC_DELMACRO), i >= 0);
					/*FALLTHROUGH*/
				case IDC_MACROREPLACE:
					if (NOTIFICATION != EN_CHANGE || InitialString) break;
					/*FALLTHROUGH*/
				case IDC_INSERTMODE:
				case IDC_COMMANDMODE:
				case IDC_COMMANDLINE:
				case IDC_MAP:
				case IDC_ABBREV:
					if (COMMAND == IDC_ABBREV || COMMAND == IDC_MAP) {
						if (COMMAND == IDC_ABBREV)
							CheckDlgButton(hDlg, IDC_COMMANDMODE, FALSE);
						EnableWindow(GetDlgItem(hDlg, IDC_COMMANDMODE),
									 COMMAND == IDC_MAP);
					}
					if (GetDlgItemText(hDlg, IDC_MACRONAME, Buf, sizeof(Buf)) &&
						GetDlgItemText(hDlg, IDC_MACROINPUT,Buf, sizeof(Buf))) {
							SendMessage(hwndSettings, DM_SETDEFID, 102, 0);
							SendMessage(hDlg, DM_SETDEFID, IDC_SETMACRO, 0);
					}
					break;

				case IDC_SETMACRO:
					ThisMapping = calloc(1, sizeof(*ThisMapping));
					if (ThisMapping != NULL) {
						PMAP *pmNew, *pmFree = NULL;

						/*create a new entry...*/
						GetDlgItemText(hDlg, IDC_MACROINPUT, Buf, sizeof(Buf));
						if (!AllocStringA	 (&ThisMapping->InputDisplay,Buf) ||
							!TranslateMapping(&ThisMapping->InputMatch,  Buf)) {
								FreeMappings(ThisMapping);
								break;
						}
						GetDlgItemText(hDlg, IDC_MACROREPLACE,Buf,sizeof(Buf));
						if (!AllocStringA	 (&ThisMapping->Replace,	 Buf) ||
							!TranslateMapping(&ThisMapping->ReplaceMap,  Buf)) {
								FreeMappings(ThisMapping);
								break;
						}
						GetDlgItemText(hDlg, IDC_MACRONAME, Buf, sizeof(Buf));
						if (!AllocStringA(&ThisMapping->Name,	Buf)) {
							FreeMappings(ThisMapping);
							break;
						}
						ThisMapping->Flags	 = 0;
						if (IsDlgButtonChecked(hDlg, IDC_ABBREV))
							ThisMapping->Flags |= M_ABBREVIATION;
						if (IsDlgButtonChecked(hDlg, IDC_INSERTMODE))
							ThisMapping->Flags |= M_INSERTMODE;
						if (IsDlgButtonChecked(hDlg, IDC_COMMANDMODE))
							ThisMapping->Flags |= M_COMMANDMODE;
						if (IsDlgButtonChecked(hDlg, IDC_COMMANDLINE))
							ThisMapping->Flags |= M_COMMANDLINE;
						/*find old entry to delete and new position to enter..*/
						for (MapPtr = pmNew = &NewMappings;
								(m = *MapPtr) != NULL;
								MapPtr = &m->Next) {
							if ((i = lstrcmp(m->Name, Buf)) >= 0) {
								if (i == 0) {
									pmFree = MapPtr;
									break;
								}
							} else pmNew = &m->Next;
							if (IsMappingEqual(m->InputMatch,
											   ThisMapping->InputMatch) &&
									(m->Flags & ThisMapping->Flags) == m->Flags)
								pmFree = MapPtr;
						}
						/*delete old entry*/
						if (pmFree != NULL) {
							PMAP ToFree = *pmFree;

							if ((i = FindMacroName(ListBox, ToFree->Name)) >= 0)
								SendMessage(ListBox, LB_DELETESTRING, i, 0);
							*pmFree = ToFree->Next;
							if (pmNew == &ToFree->Next) pmNew = pmFree;
							ToFree->Next = NULL;
							FreeMappings(ToFree);
						}
						/*enter new entry...*/
						i = SendMessage(ListBox, LB_ADDSTRING, 0,
										(LPARAM)ThisMapping->Name);
						SendMessage(ListBox, LB_SETCURSEL, i, 0);
						ThisMapping->Next = *pmNew;
						*pmNew = ThisMapping;
					}
					EnableWindow(GetDlgItem(hDlg, IDC_DELMACRO), TRUE);
					DefaultOkButton(hDlg);
					break;

				case IDC_DELMACRO:
					i = SendMessage(ListBox, LB_GETCURSEL, 0, 0);
					if (i != LB_ERR) {
						SendMessage(ListBox, LB_GETTEXT, i, (LPARAM)(LPSTR)Buf);
						for (MapPtr = &NewMappings;
							 *MapPtr != NULL
								&& lstrcmp((*MapPtr)->Name, Buf);
							 MapPtr = &(*MapPtr)->Next);
						if ((ThisMapping = *MapPtr) != NULL) {
							HWND DelButton = GetDlgItem(hDlg, IDC_DELMACRO);

							*MapPtr = ThisMapping->Next;
							ThisMapping->Next = NULL;
							FreeMappings(ThisMapping);
							SendMessage(ListBox, LB_DELETESTRING, i, 0);
							DefaultOkButton(hDlg);
							EnableWindow(DelButton, FALSE);
							SendMessage(DelButton, BM_SETSTYLE, (WPARAM)BS_PUSHBUTTON, 1);
							SetFocus(ListBox);
						}
					}
					break;

				case IDOK:
				case ID_APPLY:
				case IDC_STORE:
					FreeMappings(FirstMapping);
					FirstMapping = NewMappings;
					NewMappings = NULL;
					DlgResult = TRUE;
					if (COMMAND == IDC_STORE) SaveMappingSettings();
					if (COMMAND == IDOK)	  EndDialog(hDlg, 0);
					else MacrosCallback(hDlg, WM_INITDIALOG, 0, 0);
					break;

				case IDCANCEL:
					FreeMappings(NewMappings);
					NewMappings = NULL;
					EndDialog(hDlg, 0);
					break;
			}
			break;

		default:
			return (FALSE);
	}
	return (TRUE);
}