Team OS/2 Italia - Developer Assistant

------------------------------------------

INI Copier v1.00

Un esempio di programma PM Multi-Threaded

list.c

/***************************************************************************
 
 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 */

---------------------------------------------------

Torna alla nostra HomePage - Pagina a cura di: Giovanni Pagni
Last modified 27-10-97