/***************************************************************************
List for INI Copier
****************************************************************************/
#define INCL_WINLISTBOXES
#include "global.h"
#include "resource.h"
#include <string.h>
/* macro definitions */
/* global variables */
/* function prototypes */
/* Crea la sottolista associata ad un'applicazione */
PrfSubItem *MakeSubList(HINI hPrf,PSZ AppName);
/* Conta il numero di elementi nella lista delle applicazioni */
int GetListSize(PrfItem *Head);
/* Conta il numero di elementi in una sottolista */
int GetSubListSize(PrfSubItem *Head);
/* implementation */
/* Aggiunge un elemento alla lista delle applicazioni */
PrfItem *AddItem(PrfItem *Head, PSZ Name, HWND hList)
{
PrfItem *NewHead;
/* alloca la memoria per la struttura */
NewHead=(PrfItem *)Memory(sizeof(PrfItem));
/* Crea un blocco nuovo per il nome aggiunto. Questo metodo puo` sembrare
non molto eficace ma mediamente sarebbe molta di piu` la memoria sprecata
se memorizzassi separatamente ogni nome al momento della lettura da
un profilo */
NewHead->Block=(BlockInfo *)Memory(sizeof(BlockInfo)+strlen(Name)+1);
NewHead->Block->Count=1;
NewHead->Name=(PSZ)(NewHead->Block+1);
/* Copio il nome */
strcpy(NewHead->Name,Name);
/* Il nuovo elemento diventa la nuova testa della lista */
NewHead->Next=Head;
/* non ci sono sottoliste */
NewHead->SubList=NULL;
/* Aggiunge l'elemento alla listbox */
WinSendMsg(hList,LM_INSERTITEM,MPFROMSHORT(LIT_SORTASCENDING),Name);
/* restituisce la nuova testa della lista */
return NewHead;
}
/* Aggiunge un elemento alla sottolista */
PrfSubItem *AddSubItem(PrfSubItem *Head, PSZ Name)
{
PrfSubItem *NewHead;
/* Alloca la memoria per la struttura */
NewHead=(PrfSubItem *)Memory(sizeof(PrfItem));
/* crea un nuovo blocco */
NewHead->Block=(BlockInfo *)Memory(sizeof(BlockInfo)+strlen(Name)+1);
NewHead->Block->Count=1;
NewHead->Name=(PSZ)(NewHead->Block+1);
/* copia il nome */
strcpy(NewHead->Name,Name);
/* il nuovo elemento diventa la test della lista */
NewHead->Next=Head;
/* restituisce la nuova testa della lista */
return NewHead;
}
/* cancella un elemento dalla lista delle applicazioni */
PrfItem *DeleteItem(PrfItem *Head, PSZ Name, HWND hList)
{
PrfItem *Item; /* elemento temporaneo */
PrfItem *Last=NULL; /* elemento temporaneo */
SHORT index;
/* ottiene l'indice dell'elemento nella listbox e se non lo trova
ritorna senza fare niente, altrimenti lo cancella */
index=(SHORT)WinSendMsg(hList,LM_SEARCHSTRING,
MPFROM2SHORT(LSS_CASESENSITIVE,LIT_FIRST),
(MPARAM)Name);
if(index==LIT_ERROR || index==LIT_NONE)
return Head;
WinSendMsg(hList,LM_DELETEITEM,MPFROMSHORT(index),NULL);
Item=Head;
/* percorre la lista finche` non trova l'elemento */
while(Item != NULL)
{
PrfSubItem *SubItem;
if(!strcmp(Item->Name,Name))
{
/* Decrementa il conteggio degli elementi nel blocco e se non
ce ne sono piu` libera la memoria del blocco */
if(--Item->Block->Count == 0)
MemFree(Item->Block);
/* Controlla se c'e` la sottolista, ed eventualmente la cancella */
SubItem=Item->SubList;
while(SubItem != NULL)
{
PrfSubItem *LastSubItem;
/* percorre tutta la sottolista cancellandola */
if(--SubItem->Block->Count == 0)
MemFree(SubItem->Block);
LastSubItem=SubItem->Next;
MemFree(SubItem);
SubItem=LastSubItem;
}
/* Se non era il primo elemento della lista aggiorna il link
dell'elemento precedente in modo da saltare l'elemnto cancellato */
if(Last != NULL)
Last->Next=Item->Next;
else
/* se invece era l'inizio della lista si cambia l'inizio */
Head=Item->Next;
/* si puo` cancellare l'elemento e interrompere la ricerca */
MemFree(Item);
break;
}
/* aggiorna l'elemnto precedente e seleziona il successivo */
Last=Item;
Item=Item->Next;
}
return Head;
}
/* cancella un elemento dalla sottolista (e` praticamente identica a
DeleteItem */
PrfSubItem *DeleteSubItem(PrfSubItem *Head, PSZ Name, HWND hSubList)
{
PrfSubItem *Item;
PrfSubItem *Last=NULL;
SHORT index;
index=(SHORT)WinSendMsg(hSubList,LM_SEARCHSTRING,
MPFROM2SHORT(LSS_CASESENSITIVE,LIT_FIRST),
(MPARAM)Name);
if(index==LIT_ERROR || index==LIT_NONE)
return Head;
WinSendMsg(hSubList,LM_DELETEITEM,MPFROMSHORT(index),NULL);
Item=Head;
while(Item != NULL)
{
if(!strcmp(Item->Name,Name))
{
if(--Item->Block->Count == 0)
MemFree(Item->Block);
if(Last != NULL)
Last->Next=Item->Next;
else
Head=Item->Next;
MemFree(Item);
break;;
}
Last=Item;
Item=Item->Next;
}
return Head;
}
/* Riempie la ListBox della sottolista */
void FillSubList(HWND hSubList, PrfSubItem *Head)
{
int i;
int ListSize;
PSZ *NameArray;
LBOXINFO ListInfo;
/* controlla che la sottolista sia valida */
if(Head != NULL)
{
/* cancella il contenuto della listbox */
WinSendMsg(hSubList,LM_DELETEALL,NULL,NULL);
/* resetta la struttura di aggiornamento della listbox */
memset(&ListInfo,0,sizeof(LBOXINFO));
/* Ottiene la dimensione della listbox e se supera il limite termina
il programma */
ListSize=GetSubListSize(Head);
if(ListSize>32768)
ErrorBox(IDE_INTERNAL,TRUE);
/* Crea un array di puntatori a stringhe */
NameArray=(PSZ *)Memory(ListSize*sizeof(PSZ));
/* Gli dico di ordinare gli elementi in ordine crescente */
ListInfo.lItemIndex=LIT_SORTASCENDING;
ListInfo.ulItemCount=ListSize;
/* Riempio l'array di puntatori percorrendo la lista */
i=0;
while(Head != NULL)
{
NameArray[i++]=Head->Name;
Head=Head->Next;
}
/* Inserisce gli elementi nella ListBox */
WinSendMsg(hSubList,LM_INSERTMULTITEMS,&ListInfo,NameArray);
MemFree(NameArray);
}
}
/* Questa funzione trova un'applicazione nella lista a partire
dall'elemento che viene passato come Head */
PrfItem *FindItem(PrfItem *Head, PSZ Name)
{
while(Head != NULL)
{
/* confronta il nome dell'applicazione e se e` quello giusto
restituisce il puntatore alla struttura */
if(!strcmp(Head->Name,Name))
return Head;
Head=Head->Next;
}
return NULL;
}
/* Questa funzione trova una sottosezione nella lista a partire
dall'elemento che viene passato come Head */
PrfSubItem *FindSubItem(PrfSubItem *Head, PSZ Name)
{
while(Head != NULL)
{
/* cnfronta il nome della sottosezione */
if(!strcmp(Head->Name,Name))
return Head;
Head=Head->Next;
}
return NULL;
}
/* Percorre la lista contando gli elementi presenti da Head fino alla fine */
int GetListSize(PrfItem *Head)
{
int count=0;
while(Head != NULL)
{
count++;
Head=Head->Next;
}
return count;
}
/* Percorre la sottolista contando gli elementi da Head fino alla fine */
int GetSubListSize(PrfSubItem *Head)
{
int count=0;
while(Head != NULL)
{
count++;
Head=Head->Next;
}
return count;
}
/* Riempie entrambe le ListBox di un profilo */
void FillLists(HWND hList,HWND hSubList,PrfItem *Head)
{
int i;
int ListSize;
PSZ *NameArray;
LBOXINFO ListInfo;
PrfItem *Item;
/* Verifica che la lista sia valida */
if(Head != NULL)
{
/* Cancella tutti gli elementi nella listbox */
WinSendMsg(hList,LM_DELETEALL,NULL,NULL);
Item=Head;
/* Prepara la struttura LBOXINFO */
memset(&ListInfo,0,sizeof(LBOXINFO));
/* Verifica che nella lista non ci siano piu` elementi del massimo
contenibile da una listbox */
ListSize=GetListSize(Head);
if(ListSize>32768)
ErrorBox(IDE_INTERNAL,TRUE);
/* Prepara un array di puntatori a sringhe da passare alla listbox */
NameArray=(PSZ *)Memory(ListSize*sizeof(PSZ));
/* Compila la struttura LBOXINFO */
ListInfo.lItemIndex=LIT_SORTASCENDING;
ListInfo.ulItemCount=ListSize;
i=0;
while(Item != NULL)
{
NameArray[i++]=Item->Name;
Item=Item->Next;
}
/* Inserisce gli elementi nella lista */
WinSendMsg(hList,LM_INSERTMULTITEMS,&ListInfo,NameArray);
/* Rilascia l'array di puntatori */
MemFree(NameArray);
/* Aggiorna la sottolista semplicemente selezionando il
primo elemento della lista */
WinSendMsg(hList,LM_SELECTITEM,(MPARAM)0,(MPARAM)TRUE);
}
}
/* Costruisce la lista delle applicazioni e le rispettive liste delle
sottosezioni */
PrfItem *BuildLists(HINI hPrf)
{
BOOL rc;
ULONG Size;
ULONG Length;
char *AppBuffer;
int items;
PrfItem *Head=NULL;
PrfItem *Item;
BlockInfo *Block;
/* Richiede la dimensione di memoria necessaria per contenere tutti i nomi
delle applicazioni */
rc=PrfQueryProfileSize(hPrf,NULL,NULL,&Size);
if(!rc)
{
ErrorBox(IDE_INTERNAL,FALSE);
return NULL;
}
/* Crea il blocco di memoria per tutti i nomi delle applicazioni */
Block=(BlockInfo *)Memory(++Size + sizeof(BlockInfo));
AppBuffer=(char *)(Block+1);
/* Richiede tutti i nomi delle applicazioni se c'e` un errore libera
il blocco di memoria */
Length=PrfQueryProfileString(hPrf,NULL,NULL,NULL,AppBuffer,Size);
if(*AppBuffer==0)
{
MemFree(Block);
return NULL;
}
/* items Conta le applicazioni */
items=0;
while(Length>0)
{
/* Se stiamo creando il primo elemento lo salviamo anche in Head
per ricordarci l'inizio della lista */
if(items==0)
{
Head=(PrfItem *)Memory(sizeof(PrfItem));
Item=Head;
}
else
{
/* Altrimenti si aggiorna il campo Next e Item */
Item->Next=(PrfItem *)Memory(sizeof(PrfItem));
Item=Item->Next;
}
/* Ogni elemento ha un puntatore al blocco in cui e` contenuto il
nome dell'applicazione */
Item->Block=Block;
Item->Name=AppBuffer;
/* Passa al nome dell'applicazione successiva. La variabile Length
viene decrementata in modo da terminare il loop quando sono state
processate tutte le applicazioni */
while(*AppBuffer++!=0)
Length--;
Length--;
/* Costruisce la sottolista */
Item->SubList=MakeSubList(hPrf,Item->Name);
/* Si considera che questo sia l'ultimo elemento */
Item->Next=NULL;
/* Conta le applicazioni contenute in questo blocco */
items++;
}
/* Setta il numero di applicazioni presenti nel blocco */
Block->Count=items;
return Head;
}
/* Questa funzione costruisce la lista delle sottosezioni per una
certa appplicazione. Il funzionamento e` pressoche` identico a quello di
BuildLists */
PrfSubItem *MakeSubList(HINI hPrf,PSZ AppName)
{
BOOL rc;
ULONG Size;
ULONG Length;
PrfSubItem *Item;
PrfSubItem *Head=NULL;
BlockInfo *Block;
char *KeyBuffer;
int items;
rc=PrfQueryProfileSize(hPrf,AppName,NULL,&Size);
if(!rc)
{
ErrorBox(IDE_INTERNAL,FALSE);
return NULL;
}
Block=(BlockInfo *)Memory(++Size + sizeof(BlockInfo));
KeyBuffer=(char *)(Block+1);
Length=PrfQueryProfileString(hPrf,AppName,NULL,NULL,KeyBuffer,Size);
if(*KeyBuffer==0)
{
MemFree(Block);
return NULL;
}
items=0;
while(Length>0)
{
if(items==0)
{
Head=(PrfSubItem *)Memory(sizeof(PrfSubItem));
Item=Head;
}
else
{
Item->Next=(PrfSubItem *)Memory(sizeof(PrfSubItem));
Item=Item->Next;
}
Item->Block=Block;
Item->Name=KeyBuffer;
while(*KeyBuffer++!=0)
Length--;
Length--;
Item->Next=NULL;
items++;
}
Block->Count=items;
return Head;
}
/* Questa funzione distrugge entrambe le liste */
BOOL ClearLists(PrfItem *Item)
{
PrfSubItem *SubItem;
/* continua fintanto che e` giunti all'ultimo elemento della lista */
while(Item != NULL)
{
PrfItem *Next;
/* Si salva il valore del campo Next */
Next=Item->Next;
/* Se sono stati distrutti tutti gli elementi nel blocco si libera la
memoria del blocco */
if(--Item->Block->Count == 0)
MemFree(Item->Block);
SubItem=Item->SubList;
/* Se c'e` una sottolista si distrugge */
while(SubItem != NULL)
{
PrfSubItem *SubNext;
SubNext=SubItem->Next;
if(--SubItem->Block->Count == 0)
MemFree(SubItem->Block);
MemFree(SubItem);
SubItem=SubNext;
}
/* Si libera l'elemento */
MemFree(Item);
/* Si passa al successivo */
Item=Next;
}
return TRUE;
}
/* fine di list.c */
Last modified 27-10-97 |