Terminata la gestione del bottone (unico!) negli sheet git-svn-id: svn://10.65.10.50/trunk@756 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			697 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			697 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| 
 | |
| #include "ccommon.h"
 | |
| #include "genconst.h"
 | |
| #include "ccustio.h"
 | |
| #include "cbpltree.h"
 | |
| #include "bplpriv.h"
 | |
| #include "btrread.h"
 | |
| #include "btrbase.h"
 | |
| #include "checks.h"
 | |
| #include        <memory.h>
 | |
| 
 | |
| 
 | |
|  void Move(byte ,int ,int ,int ,char *,char *);
 | |
| 
 | |
| /*
 | |
| @(SHF) Funzioni di base per il B+Tree
 | |
| @($) ZPage  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Azzera una pagina del B+TREE.
 | |
| @(FD)
 | |
| */
 | |
| 
 | |
| 	void                            ZPage(ActPage)
 | |
| 	Page                            *ActPage; /* pagina attuale */
 | |
| 
 | |
| 		{ 
 | |
| 
 | |
| 			ActPage->PA.PageHeader.TPage = EmptyPage;
 | |
| 			ActPage->PA.PageHeader.PathNumber = 0;
 | |
| 			ActPage->PA.PageHeader.Flags = 0;
 | |
| 			ActPage->PA.PageHeader.Father = NoLink;
 | |
| 			ActPage->PA.PageHeader.Prev = NoLink;
 | |
| 			ActPage->PA.PageHeader.Next = NoLink;
 | |
| 			ActPage->PA.PageHeader.NKey = 0;
 | |
| 			memset(ActPage->PA.AreaForKey, ' ', AreaLen);
 | |
| 		}
 | |
| 
 | |
| /*
 | |
| @($) GetHeader  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Legge l'header di un indice.
 | |
| Restituisce il codice di errore.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| junk = variabile spazzatura per la chiamata della funzione "sleep".
 | |
| 
 | |
| w    = descrittore della finestra.
 | |
| 
 | |
| @(FSV)
 | |
| 
 | |
| */
 | |
| 
 | |
| 	int                                     GetHeader(FilCheck, HPage, LockMode, Err)
 | |
| 	FilCtrl                 *FilCheck; /* identificatore indice             */
 | |
| 	Page                            *HPage;    /* pagina dell' indice  */
 | |
| 	int                                     LockMode;  /* lock sull'header                  */
 | |
| 	int                                     *Err;      /* codice di errore                  */
 | |
| 
 | |
| 	{
 | |
| 	  do
 | |
| 	  {
 | |
| 	    CRead(&FilCheck->Fil, (char *) HPage, 1L, LockMode);
 | |
| 	    if (TESTLOCK(FilCheck->Fil.IOR))
 | |
| 	      message_box("Sono in attesa dell' indice");
 | |
| 	  } while TESTLOCK(FilCheck->Fil.IOR);
 | |
| 	  return((*Err = FilCheck->Fil.IOR));
 | |
| 	}
 | |
| 
 | |
| /*
 | |
| @($) PutHeader  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Scrive l'header di un indice.
 | |
| Restituisce il codice di errore.
 | |
| @(FD)
 | |
| */
 | |
| 
 | |
| 	int                                     PutHeader(FilCheck, HPage, LockMode, Err)
 | |
| 	FilCtrl                 *FilCheck; /* identificatore indice    */
 | |
| 	Page                            *HPage;    /* pagina in cui scrivere l'header */
 | |
| 	int                                     LockMode;  /* lock sull'header                */
 | |
| 	int                                     *Err;      /* errore                          */
 | |
| 
 | |
| 			{
 | |
| 				CWrite(&FilCheck->Fil, (char *) HPage, 1L, LockMode);
 | |
| 				return((*Err = FilCheck->Fil.IOR));
 | |
| 			}
 | |
| 
 | |
| /*
 | |
| @($) GetAPage  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Legge una pagina generica dell'indice.
 | |
| Restituisce il codice di errore.
 | |
| @(FD)
 | |
| */
 | |
| 
 | |
| 	int                                     GetAPage(FilCheck, ActPage, Pg, Err)
 | |
| 	FilCtrl                 *FilCheck; /* identificatore indice */
 | |
| 	Page                            *ActPage;  /* pagina letta          */
 | |
| 	RecNoType               Pg;        /* numero di pagina      */
 | |
| 	int                                     *Err;      /* codice di errore      */
 | |
| 
 | |
| 		{
 | |
| 			CRead(&FilCheck->Fil, (char *) ActPage, Pg + FilCheck->FHead.CABlock + 1,
 | |
| 						NoLock);
 | |
| 			return((*Err = FilCheck->Fil.IOR)); 
 | |
| 		}
 | |
| 
 | |
| /*
 | |
| @($) PutAPage  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Scrive una pagina generica dell'indice.
 | |
| Restituisce il codice di errore.
 | |
| @(FD)
 | |
| */
 | |
| 
 | |
| 	int                                     PutAPage(FilCheck, ActPage, Pg, Err)
 | |
| 	FilCtrl                 *FilCheck; /* identificatore indice */
 | |
| 	Page                            *ActPage;  /* pagina attiva         */
 | |
| 	RecNoType               Pg;        /* numero della pagina   */
 | |
| 	int                                     *Err;      /* codice errore         */
 | |
| 
 | |
| 		{
 | |
| 			CWrite(&FilCheck->Fil, (char *) ActPage, Pg + FilCheck->FHead.CABlock + 1,
 | |
| 							NoLock);
 | |
| 			return((*Err = FilCheck->Fil.IOR)); 
 | |
| 		}
 | |
| 
 | |
| /*
 | |
| @($) GetAKey  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Estrae una chiave da una pagina.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| BgnItem = numero di byte precedenti alla chiave dall'inizio della pagina.
 | |
| @(FSV)
 | |
| */
 | |
| 
 | |
| 	void                            GetAKey(ActPage, KeyLen, Pstion, KKey, Index)
 | |
| 	Page                            ActPage; /* pagina attiva                    */
 | |
| 	int                                     KeyLen;  /* lunghezza della chiave           */
 | |
| 	int                                     Pstion;  /* numero chiave nella pagina       */
 | |
| 	TKey                            KKey;    /* Valore chiave (in output)        */
 | |
| 	RecNoType               *Index;  /* indice associato a questa chiave */
 | |
| 
 | |
| 		{
 | |
| 			int                                BgnItem;
 | |
| 
 | |
| 			BgnItem = (Pstion - 1) * (KeyLen + IndLen);
 | |
| 			strcpy(KKey, (char *)(ActPage.PA.AreaForKey + BgnItem));
 | |
| 			*Index = *((RecNoType *)(ActPage.PA.AreaForKey + BgnItem + KeyLen));
 | |
| 		}
 | |
| 
 | |
| /*
 | |
| @($) PutAKey  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Mette una chiave in una pagina.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| BgnItem = numero di byte precedenti alla chiave dall'inizio della pagina.
 | |
| @(FSV)
 | |
| */
 | |
| 
 | |
| 	void                            PutAKey(KKey, Index, Pstion, KeyLen, ActPage)
 | |
| 	TKey                            KKey;    /* valore della chiave             */
 | |
| 	RecNoType               Index;   /* indice                          */
 | |
| 	int                                     Pstion;  /* posizione nella quale scrivere la chiave */
 | |
| 	int                                     KeyLen;  /* lunghezza della chiave          */
 | |
| 	Page                            *ActPage;/* pagina attiva                   */
 | |
| 
 | |
| 		{
 | |
| 			register int                                    BgnItem;
 | |
| 
 | |
| 			BgnItem = (Pstion - 1) * (KeyLen + IndLen);
 | |
| 			strcpy((char *)(ActPage->PA.AreaForKey + BgnItem), KKey);
 | |
| 			*((RecNoType *)(ActPage->PA.AreaForKey + BgnItem + KeyLen)) = Index;
 | |
| 		}
 | |
| 
 | |
| /*
 | |
| @($) Repos  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Riposizione all'ultima chiave letta dall'ultima operazione.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| WKey, WKey1 = variabili di lavoro contenenti chiavi.
 | |
| 
 | |
| WPos        = variabile di lavoro contenente il numero di chiave nella pagina.
 | |
| 
 | |
| WPag        = variabile di lavoro contenente il numero di pagina attuale.
 | |
| 
 | |
| WInd,WInd1  = variabili di lavoro contenenti indici associati alle chavi Wkey.
 | |
| @(FSV)
 | |
| 
 | |
| @(IN)
 | |
| Serve solo in multiutenza (XENIX).
 | |
| @(FN)
 | |
| */
 | |
| 
 | |
| 	void                            Repos(FilCheck, BError)
 | |
| 	FilCtrl                 *FilCheck;  /* identificatore indice     */
 | |
| 	int                                     *BError;    /* codice errore (in output) */
 | |
| 
 | |
| 	{
 | |
| 		TKey                    WKey, WKey1;
 | |
| 		int                             WPos = FilCheck->Pos, WError;
 | |
| 		RecNoType       WPag = FilCheck->CurPag, WInd, WInd1;
 | |
| 
 | |
| 		if (GetAPage(FilCheck, &PathPage, WPag, BError) != NoErr) return;
 | |
| 		if (PathPage.PA.PageHeader.NKey < WPos) WPos = PathPage.PA.PageHeader.NKey ;
 | |
| 		GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, WPos, WKey, &WInd);
 | |
| 		if ((strcmp(WKey, FilCheck->Key) == 0) && (WInd == FilCheck->Ind)) return ;
 | |
| 		strcpy(WKey1, FilCheck->Key) ;
 | |
| 		WInd = FilCheck->Ind ;
 | |
| 		BTrRead(FilCheck, FilCheck->Key, WKey, &WInd1, BError) ;
 | |
| 		WPag =	FilCheck->CurPag ;
 | |
| 		WPos =	FilCheck->Pos ;
 | |
| 		if (*BError == BTrEmptyTree) return ;
 | |
| 		if (FilCheck->Base[FilCheck->PN].DupKeys == TRUE)
 | |
| 		{
 | |
| 			while ((strcmp(WKey, WKey1) == 0) && (WInd1 < WInd))
 | |
| 			{
 | |
| 				if (WPos < PathPage.PA.PageHeader.NKey) WPos++;
 | |
| 				else
 | |
| 					if (PathPage.PA.PageHeader.Next == NoLink) break;
 | |
| 					else
 | |
| 					{
 | |
| 						WPag = PathPage.PA.PageHeader.Next;
 | |
| 						if (GetAPage(FilCheck, &PathPage, WPag, BError) != NoErr) return;
 | |
| 						WPos = 1;
 | |
| 					}
 | |
| 				GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, WPos, WKey, &WInd1);
 | |
| 			}
 | |
| 		}
 | |
| 		if (GetAPage(FilCheck, &PathPage, WPag, &WError) != NoErr) return;
 | |
| 		if ((strcmp(WKey, WKey1) == 0) && (WInd == WInd1))
 | |
| 		{
 | |
| 			FilCheck->CurPag = WPag;
 | |
| 			FilCheck->Pos = WPos;
 | |
| 		}
 | |
| 		else 
 | |
| 		{
 | |
| 			if (*BError != BTrEOF)
 | |
| 			{
 | |
| 				FilCheck->CurPag = WPag;
 | |
| 				FilCheck->Pos = WPos;
 | |
| 				strcpy(FilCheck->Key, WKey) ;
 | |
| 				FilCheck->Ind = WInd1;
 | |
| 				*BError = BTrKeyNotFound;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| /*
 | |
| @($) BTrNext  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Restituisce la chiave successiva all'ultima letta.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| WKey = variabile di lavoro contenente la chiave.
 | |
| 
 | |
| - Versione DOS e XENIX
 | |
| @(FSV)
 | |
| */
 | |
| 
 | |
| 	void                            BTrNext(FilCheck, KKey, IndSr, BError)
 | |
| 	FilCtrl                 *FilCheck; /* identificatore indice   */
 | |
| 	TKey                            KKey;      /* valore della chiave     */
 | |
| 	RecNoType               *IndSr;    /* indice associato        */
 | |
| 	int                                     *BError;   /* codice errore           */
 | |
| 
 | |
| 		{
 | |
| 			TKey                    WKey;
 | |
| 
 | |
| 			if (FilCheck->CurPag == NoLink)
 | |
| 			{
 | |
| 				MaxKey(FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Key);
 | |
| 				BTrRead(FilCheck, FilCheck->Key, WKey, IndSr, BError) ;
 | |
| 				*BError = BTrEOF;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
|  			  Repos(FilCheck, BError) ;
 | |
| 				if (*BError != NoErr)
 | |
| 				{
 | |
| 					if (*BError == BTrKeyNotFound)
 | |
| 					{
 | |
| 						strcpy(KKey,FilCheck->Key);
 | |
| 						*IndSr = FilCheck->Ind ;
 | |
| 						*BError = NoErr ;
 | |
| 					}
 | |
| 					return;
 | |
| 				}
 | |
| 				if (FilCheck->Pos < PathPage.PA.PageHeader.NKey)
 | |
| 				{
 | |
| 					FilCheck->Pos++;
 | |
| 					GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					if (PathPage.PA.PageHeader.Next == NoLink)
 | |
| 					{
 | |
| 						GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | |
| 						/*MaxKey(FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Key);*/
 | |
| 						*BError = BTrEOF;
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						FilCheck->CurPag = PathPage.PA.PageHeader.Next;
 | |
| 						if (GetAPage(FilCheck, &PathPage, FilCheck->CurPag, BError) != NoErr) return;
 | |
| 						FilCheck->Pos = 1;
 | |
| 						GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | |
| 					}
 | |
| 				}
 | |
| 				strcpy(KKey,FilCheck->Key);
 | |
| 				FilCheck->Ind = *IndSr ;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| /*
 | |
| @($) BTrPrev  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Restituisce la chiave successiva all'ultima.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| WKey = variabile di lavoro contenente una chiave.
 | |
| 
 | |
| - Versione DOS e XENIX
 | |
| @(FSV)
 | |
| */
 | |
| 
 | |
| 	void                            BTrPrev(FilCheck, KKey, IndSr, BError)
 | |
| 	FilCtrl                 *FilCheck; /* identificatore indice  */
 | |
| 	TKey                            KKey;      /* valore della chiave (in output) */
 | |
| 	RecNoType               *IndSr;    /* indice associato       */
 | |
| 	int                                     *BError;   /* codice di errore       */
 | |
| 
 | |
| 		{
 | |
| 			TKey                    WKey;
 | |
| 
 | |
| 			if (FilCheck->CurPag == NoLink)
 | |
| 			{
 | |
| 				MinKey(FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Key);
 | |
| 				BTrRead(FilCheck, FilCheck->Key, WKey, IndSr, BError) ;
 | |
| 				*BError = BTrBOF;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				Repos(FilCheck, BError) ;
 | |
| 				if ((*BError != NoErr) && (*BError != BTrKeyNotFound))
 | |
| 				{
 | |
| 					if (*BError == BTrEOF)
 | |
| 					{
 | |
| 						strcpy(KKey,FilCheck->Key);
 | |
| 						*IndSr = FilCheck->Ind ;
 | |
| 						*BError = NoErr ;
 | |
| 					}
 | |
| 					return;
 | |
| 				}
 | |
| 				*BError = NoErr;
 | |
| 				if (FilCheck->Pos > 1)
 | |
| 				{
 | |
| 					FilCheck->Pos--;
 | |
| 					GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					if (PathPage.PA.PageHeader.Prev == NoLink)
 | |
| 					{
 | |
| 						GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | |
| 						/*MinKey(FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Key);*/
 | |
| 						*BError = BTrBOF;
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						FilCheck->CurPag = PathPage.PA.PageHeader.Prev;
 | |
| 						if (GetAPage(FilCheck, &PathPage, FilCheck->CurPag, BError) != NoErr) return;
 | |
| 						FilCheck->Pos = PathPage.PA.PageHeader.NKey;
 | |
| 						GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | |
| 					}
 | |
| 				}
 | |
| 				strcpy(KKey, FilCheck->Key);
 | |
| 				FilCheck->Ind = *IndSr ;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| /*
 | |
| @($) Move  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Sposta a destra od a sinistra un numero di byte "NByt" da una sorgente "Buff1"
 | |
| ad una destinazione "Buff2".
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| w = area di transito.
 | |
| @(FSV)
 | |
| */
 | |
| 
 | |
| 	void                            Move(RghOrLft, NByt, BytBeg, BytDest, Buff1, Buff2)
 | |
| 	byte                            RghOrLft; /* destra o sinistra */
 | |
| 	int                                     NByt;     /* numero di byte da spostare */
 | |
| 	int                                     BytBeg;   /* num. byte inizio sorgente  */
 | |
| 	int                                     BytDest;  /* num. byte inizio destinazione */
 | |
| 	AreaKey                 Buff1;    /* sorgente                      */
 | |
| 	AreaKey                 Buff2;    /* destinazione                  */
 | |
| 
 | |
| 		{
 | |
| 			AreaKey         w;
 | |
| 
 | |
| 			memcpy(w, &Buff1[BytBeg], NByt);
 | |
| 			memcpy(&Buff2[BytDest], w, NByt);
 | |
| 		}
 | |
| 
 | |
| /*
 | |
| @($) ShiftPage  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Esegue uno spostamento di un certo numero di posizioni (coppie chiave-puntatore)
 | |
| all'interno della pagina.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| Len = lunghezza di una coppia chiave-puntatore.
 | |
| 
 | |
| Beg = numero di byte dall'inizio della pagina alla chiave "StartK" (esclusa).
 | |
| 
 | |
| Dest =  byte al quale si deve postare la coppia chiave-puntatore.
 | |
| @(FSV)
 | |
| */
 | |
| 
 | |
| 	void                            ShiftPage(RghOrLft, StartK, NPos, MxKey, KeyLen, Page1)
 | |
| 	byte                            RghOrLft; /* destra o sinistra  */
 | |
| 	int                                     StartK;   /* chiave di partenza */
 | |
| 	int                                     NPos;     /* numero di posizioni da saltare  */
 | |
| 	int                                     MxKey;    /* numero max chiavi in una pagina */
 | |
| 	int                                     KeyLen;   /* lunghezza di una chiave         */
 | |
| 	Page                            *Page1;   /* pagina attiva                   */
 | |
| 
 | |
| 	{
 | |
| 		register int                                    Len = KeyLen + IndLen;
 | |
| 		register int                                    Beg = (StartK - 1) * Len;
 | |
| 		register int                                    Dest;
 | |
| 
 | |
| 		if (RghOrLft == RightDir)
 | |
| 		{
 | |
| 			Dest = Beg + NPos * Len;
 | |
| 			if (Page1->PA.PageHeader.NKey + NPos <= MxKey)
 | |
| 			{
 | |
| 				Move(RightDir, (Page1->PA.PageHeader.NKey - StartK + 1) * Len, Beg, Dest, Page1->PA.AreaForKey, Page1->PA.AreaForKey);
 | |
| 				Page1->PA.PageHeader.NKey += NPos;
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			Dest = Beg - NPos * Len;
 | |
| 			if (StartK - NPos > 0)
 | |
| 			{
 | |
| 				if (StartK <= Page1->PA.PageHeader.NKey)
 | |
| 					Move(LeftDir, (Page1->PA.PageHeader.NKey - StartK + 1) * Len, Beg, Dest, Page1->PA.AreaForKey, Page1->PA.AreaForKey);
 | |
| 				Page1->PA.PageHeader.NKey -= NPos;
 | |
| 				memset(&Page1->PA.AreaForKey[Page1->PA.PageHeader.NKey * Len], ' ', NPos * Len);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| /*
 | |
| @($) ShiftOut  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Sposta un certo numero di chiavi da una pagina.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| Len = lunghezza coppia chiave-puntatore.
 | |
| @(FSV)
 | |
| */
 | |
| 
 | |
| 	void                            ShiftOut(FromK, Numk, ToK, KeyLen, Page1, Page2)
 | |
| 	int                                     FromK; /* prima chiave da spostare               */
 | |
| 	int                                     Numk;  /* numero di chiavi da spostare           */
 | |
| 	int                                     ToK;   /* posizione nella pagina destinazione    */
 | |
| 	int                                     KeyLen;/* lunghezza della chiave                 */
 | |
| 	Page                            *Page1;/* puntatore alla pagina destinazione     */
 | |
| 	Page                            *Page2;/* puntatore alla pagina sorgente         */
 | |
| 
 | |
| 	{
 | |
| 		register int                                    Len = KeyLen + IndLen;
 | |
| 
 | |
| 		if (Page1->PA.PageHeader.TPage == Page2->PA.PageHeader.TPage)
 | |
| 			Move(LeftDir, Numk * Len, (FromK - 1) * Len, (ToK - 1) * Len, Page2->PA.AreaForKey, Page1->PA.AreaForKey);
 | |
| 	}
 | |
| 
 | |
| /*
 | |
| @($) FindPos  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Cerca una chiave all'interno di una pagina.
 | |
| Restituisce la chiave piu' simile.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| low = numero della chiave.
 | |
| 
 | |
| j   = incremento in byte di coppia chiave puntatore.
 | |
| @(FSV)
 | |
| 
 | |
| */
 | |
| 
 | |
| 	int                                     FindPos(ActPage, KKey, KeyLen, KeyOut, IndOut)
 | |
| 	Page                            *ActPage;  /* pagina attiva          */
 | |
| 	TKey                            KKey;      /* valore chiave (input)  */
 | |
| 	int                                     KeyLen;    /* lunghezza della chiave */
 | |
| 	TKey                            KeyOut;    /* valore chiave (output) */
 | |
| 	RecNoType               *IndOut;   /* indice associato       */
 | |
| 
 | |
| 	{
 | |
| 		register int                            low = 1, j = 0;
 | |
| 
 | |
| 		while (strcmp((char *)(ActPage->PA.AreaForKey + j), KKey) < 0)
 | |
|       if (low < ActPage->PA.PageHeader.NKey)
 | |
| 			{
 | |
| 				low++;
 | |
| 				j += (KeyLen + IndLen);
 | |
| 			}
 | |
| 			else break;
 | |
| 		strcpy(KeyOut, (char *)(ActPage->PA.AreaForKey + j));
 | |
| 		*IndOut = *((RecNoType *)(ActPage->PA.AreaForKey + j + KeyLen));
 | |
| 		return(low);
 | |
| 	}
 | |
| 
 | |
| /*
 | |
| @($) PerformOp  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Effettua operazioni di Underflow e Overflow sull'indice.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| Pst    = variabile di lavoro contenente numeri chiave.
 | |
| 
 | |
| W      = contatore.
 | |
| 
 | |
| OldKey = variabile di lavoro contenente il valore di chiavi.
 | |
| @(FSV)
 | |
| */
 | |
| 
 | |
| 	void            PerformOp(RecOp,ActPage,Pg,OvUnFlow,Temp,MxKey,MnKey,KeyLen,BError)
 | |
| 	KOp                                             RecOp; /* struttura contenente le operazioni da effettuare */
 | |
| 	Page                                    *ActPage; /* pagina attiva           */
 | |
| 	RecNoType                       Pg;       /* numero pagina           */
 | |
| 	BOOLEAN                         *OvUnFlow;/* underflow opp. overflow */
 | |
| 	KeyInd                          *Temp;    /* di lavoro, contiene una coppia chiave-puntatore */
 | |
| 	int                                             MxKey;    /* numero max chiave       */
 | |
| 	int                                             MnKey;    /* numero min chiave       */
 | |
| 	int                                             KeyLen;   /* lunghezza della chiave  */
 | |
| 	int                                             *BError;  /* codice errore           */
 | |
| 
 | |
| 		{
 | |
| 			int                                     Pst, W, i;
 | |
| 			TKey                            OldKey;
 | |
| 
 | |
| 			for (W = 0; W <= 1; W++)
 | |
| 			{
 | |
| 				if (RecOp[W].FlagOp)
 | |
| 				{
 | |
| 					RecOp[W].FlagOp = FALSE;
 | |
| 					if (RecOp[W].Which == Inser)
 | |
| 					{
 | |
| 						Pst = 0;
 | |
| 						while (Pst < ActPage->PA.PageHeader.NKey )
 | |
| 						{
 | |
| 							GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | |
| 							if (IntIndex == RecOp[W].where) break;
 | |
| 						}
 | |
| 						if (ActPage->PA.PageHeader.NKey == MxKey)
 | |
| 						{
 | |
| 							GetAKey(*ActPage, KeyLen, MxKey, IntKey, &IntIndex);
 | |
| 							if (strcmp(IntKey, RecOp[W].KeyAndInd.KKey) < 0)
 | |
| 							{
 | |
| 								strcpy(Temp->KKey, RecOp[W].KeyAndInd.KKey);
 | |
| 								Temp->Ind = RecOp[W].KeyAndInd.Ind;
 | |
| 							}
 | |
| 							else
 | |
| 							{
 | |
| 								strcpy(Temp->KKey, IntKey);
 | |
| 								Temp->Ind = IntIndex;
 | |
| 								ActPage->PA.PageHeader.NKey--;
 | |
| 								ShiftPage(RightDir, Pst, OnePos, MxKey, KeyLen, ActPage);
 | |
| 								PutAKey(RecOp[W].KeyAndInd.KKey, RecOp[W].KeyAndInd.Ind, Pst, KeyLen, ActPage);
 | |
| 							}
 | |
| 							*OvUnFlow = TRUE;
 | |
| 						}
 | |
| 						else
 | |
| 						{
 | |
| 							*OvUnFlow = FALSE;
 | |
| 							if (strcmp(IntKey, RecOp[W].KeyAndInd.KKey) < 0)
 | |
| 							{
 | |
| 								ActPage->PA.PageHeader.NKey++;
 | |
| 								PutAKey(RecOp[W].KeyAndInd.KKey, RecOp[W].KeyAndInd.Ind, ActPage->PA.PageHeader.NKey, KeyLen, ActPage);
 | |
| 								RecOp[W].FlagOp = TRUE;
 | |
| 								RecOp[W].Which = Change;
 | |
| 								RecOp[W].KeyAndInd.Ind = Pg;
 | |
| 							}
 | |
| 							else
 | |
| 							{
 | |
| 								ShiftPage(RightDir, Pst, OnePos, MxKey, KeyLen, ActPage);
 | |
| 								PutAKey(RecOp[W].KeyAndInd.KKey, RecOp[W].KeyAndInd.Ind, Pst, KeyLen, ActPage);
 | |
| 							}
 | |
| 						}
 | |
| 					}
 | |
| 					else
 | |
| 						if (RecOp[W].Which == Change)
 | |
| 						{
 | |
| 							Pst = 0;
 | |
| 							GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | |
| 							while ((IntIndex != RecOp[W].KeyAndInd.Ind) && (Pst < ActPage->PA.PageHeader.NKey))
 | |
| 								GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | |
| 							if (IntIndex == RecOp[W].KeyAndInd.Ind)
 | |
| 								PutAKey(RecOp[W].KeyAndInd.KKey, IntIndex, Pst, KeyLen, ActPage);
 | |
| 							*OvUnFlow = FALSE;
 | |
| 							if ((IntIndex == RecOp[W].KeyAndInd.Ind) && (Pst == ActPage->PA.PageHeader.NKey))
 | |
| 							{
 | |
| 								RecOp[W].FlagOp = TRUE;
 | |
| 								RecOp[W].Which = Change;
 | |
| 								RecOp[W].KeyAndInd.Ind = Pg;
 | |
| 							}
 | |
| 						}
 | |
| 						else
 | |
| 							if (RecOp[W].Which == Delet)
 | |
| 							{
 | |
| 								Pst = 0;
 | |
| 								GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | |
| 								while ((IntIndex != RecOp[W].KeyAndInd.Ind) && (Pst < ActPage->PA.PageHeader.NKey))
 | |
| 									GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | |
| 								if (IntIndex == RecOp[W].KeyAndInd.Ind)
 | |
| 								{
 | |
| 									*OvUnFlow = (ActPage->PA.PageHeader.NKey == MnKey);
 | |
| 									ShiftPage(LeftDir, ++Pst, OnePos, MxKey, KeyLen, ActPage);
 | |
| 								}
 | |
| 							}
 | |
| 					if ((!OvUnFlow) && (Pst >= ActPage->PA.PageHeader.NKey))
 | |
| 					{
 | |
| 						RecOp[W].FlagOp = TRUE;
 | |
| 						RecOp[W].Which = Change;
 | |
| 						GetAKey(*ActPage, KeyLen, ActPage->PA.PageHeader.NKey, IntKey, &IntIndex);
 | |
| 						strcpy(RecOp[W].KeyAndInd.KKey, IntKey);
 | |
| 						RecOp[W].KeyAndInd.Ind = Pg;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| /*
 | |
| @($)  ZrecOp  B+TREE
 | |
| 
 | |
| @(ID)
 | |
| Azzera la struttura delle operazioni da effettuare.
 | |
| @(FD)
 | |
| 
 | |
| @(ISV)
 | |
| i = contatore.
 | |
| @(FSV)
 | |
| */
 | |
| 
 | |
| 	void                            ZRecOp(R)
 | |
| 	KOp                                     R; /* struttura operazioni da azzerare */
 | |
| 
 | |
| 		{
 | |
| 			int                                     i;
 | |
| 
 | |
| 			for (i = 0; i <= 1; i++)
 | |
| 			{
 | |
| 				R[i].FlagOp = FALSE;
 | |
| 				R[i].Which = Nothing;
 | |
| 				R[i].Posit = NoLink;
 | |
| 				R[i].where = -1;
 | |
| 				MinKey(MaxArray, R[i].KeyAndInd.KKey);
 | |
| 				R[i].KeyAndInd.Ind = NoLink;
 | |
| 			}
 | |
| 		}
 | |
| 
 |