Team OS/2 Italia - Developer Assistant

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

INI Copier v1.00

Un esempio di programma PM Multi-Threaded

MainWnd.c

/***************************************************************************
 
 Main Window for INI Copier
 
 ****************************************************************************/

#define INCL_DOSERRORS
#define INCL_DOSMODULEMGR
#define INCL_DOSRESOURCES
#define INCL_DOSPROCESS
#define INCL_WINLISTBOXES
#define INCL_WINENTRYFIELDS
#define INCL_WINBUTTONS
#define INCL_WINFRAMEMGR
#define INCL_WINSTATICS
#define INCL_WINSYS
#define INCL_WINMENUS
#define INCL_WINDIALOGS

#include "global.h"
#include "resource.h"
#include <string.h>
#include <process.h> 

/* macro definitions */

/* Numero di finestre contenute nella finestra principale */
#define     NUM_WINS                16

/* Queste macro servono per realizzare un sistema di coordinate virtuali 
 nella finestra principale per rendere possibile il ridimensionamento 
 proporzionale di tutti i controlli */
#define     WND_XGRID    			300.
#define     WND_YGRID               150.
/* XUnits e YUnits aggiornano i fattori di conversione */
#define     XUnits(x)               (fWndXUnits=((float)(x)/WND_XGRID))
#define     YUnits(x)               (fWndYUnits=((float)(x)/WND_YGRID))
/* YPoints e XPoints effettuano la conversione da coordinate virtuali a 
pixel della finestra */
#define     XPoints(x)              ((int)((x)*fWndXUnits))
#define     YPoints(x)              ((int)((x)*fWndYUnits))

/* Macro per gestire piu` comodamente gli array */
#define 	POS(x)      			ChildPos[(x)-LIST_A]
#define     hWin(x)                 hChildWnds[x-LIST_A]

/* global variables */

/* Variabili per conservare il fattore di conversione in coordinate virtuali */
static float       	fWndXUnits;
static float       	fWndYUnits;

/* array degli handle dei controlli della finestra principale */
static HWND         hChildWnds[NUM_WINS];

/* Struttura in cui sono immagazzinate le ccordinate virtuali di ogni 
controllo */
const static struct _Positions
{
	short int     x;     /* X origine */
    short int     y;     /* Y origine */
    short int     dx;    /* larghezza */
    short int     dy;    /* altezza */
} *ChildPos;

/* Strutture per i due profili */
ProfileInfo         PrfA;
ProfileInfo         PrfB;

/* function prototypes */

void SetWndPositions(POINTS pp,ULONG show); /* riposiziona tutti i controlli */
void GetWindows(HWND hWnd);  /* Riempie l'array di handle dei controlli */
void DoCommand(SHORT id,HWND hWnd);  /* Esegue un comando */
/* DoControl gestisce i messaggi dei controlli */
MRESULT DoControl(SHORT code,SHORT id,HWND hControl);
/* Ottiene il testo di una riga della ListBox */
PSZ StringFromList(HWND hWnd,SHORT Index);
/* Copia una sezione del profilo */
BOOL CopyItem(HINI Source, HINI Target, PSZ AppName, PSZ KeyName);
/* Modifica il menu` di sistema associato alla finestra */
void MakeSysMenu(HWND hWnd);
void LoadResource(HMODULE hMod); /* carica le risorse */
void FreeResource(void);         /* rilascia le risorse */

/* implementation */

/* Questa funzione intercetta tramite un subclassing i messaggi diretti al
frame e fa in modo che la finestra non possa essere ridotta troppo */
#if (defined(__IBMC__) || defined(__IBMCPP__))
/* Questa #pragma serve per esportare i simboli con il VisualAge */
	#pragma export(SubFrameProc,"SubFrameProc",2)
#endif
LINKAGE MRESULT EXPENTRY SubFrameProc(HWND hWnd,
                                      ULONG msg,
                                      MPARAM mParam1,
                                      MPARAM mParam2)
{
    PFNWP       	OldFrameProc;
    
    /* recupera il puntatore alla funzione che normalmente gestice i frame */
    OldFrameProc=(PFNWP)WinQueryWindowULong(hWnd,QWL_USER);
    
    switch(msg)
    {
        /* Questo messaggio permette di modificare i cambiamenti fatti alla
         posizione e alle dimensioni della finestra prima che siano 
         confermati, in questo modo si possono impedire certe modifiche */
        case WM_ADJUSTWINDOWPOS:
            {
                /* Ottiene il puntatore alla struttura SWP */
                PSWP    Pos=PVOIDFROMMP(mParam1);
                
                /* Verifica che le dimensioni della finestra siano maggiori
                 delle costanti MIN_XSIZE e MIN_YSIZE ed eventualmente
                 apporta le correzioni necessarie */
                if( Pos->cx < MIN_XSIZE || Pos->cy < MIN_YSIZE)
                {
                    if(Pos->cx < MIN_XSIZE)
                        Pos->cx=MIN_XSIZE;
                    if(Pos->cy < MIN_YSIZE)
                        Pos->cy=MIN_YSIZE;
                    Pos->fl&=~SWP_MOVE;
                }
            }
            break;
            
        default:
            break;
    }
    /* Tutti gli altri messaggi li faccio processare dalla funzione 
    originaria */
    return OldFrameProc(hWnd,msg,mParam1,mParam2);
}

/* Questa funzione gestisce tutti i messaggi della finestra principale */
#if (defined(__IBMC__) || defined(__IBMCPP__))
/* Questa #pragma serve per esportare i simboli con il VisualAge */
	#pragma export(MainWndProc,"MainWndProc",1)
#endif
LINKAGE MRESULT EXPENTRY MainWndProc(HWND hWnd,
                                     ULONG msg,
                                     MPARAM mParam1,
                                     MPARAM mParam2)
{
	/* Flag che mantiene lo stato di visualizzazione della finestra */
    static ULONG    swpFlags=SWP_SHOW;  
    RECTL           rect;
    
    switch(msg)
    {
        /* Questo messaggio viene inviato alla creazione della finestra */
        case WM_CREATE:
            {
                /* Carica le risorse dall'eseguibile */
                LoadResource(NULLHANDLE);
                hWin(LIST_A)=NULLHANDLE; /* Azzera il primo handle */
                /* Cancella le strutture dei profili */
                memset(&PrfA,0,sizeof(PrfA));
                memset(&PrfB,0,sizeof(PrfB));
                PrfA.Status=closed;
                PrfB.Status=closed;
                /* Modifica il menu` di sistema */
                MakeSysMenu(hWnd);
            }
            break;
            
        /* La finestra ha cambiato dimensione */
        case WM_SIZE:
            {
                POINTS   WndSize;
                
                /* Se non e` gia` stat riempita si riempie l'array degli
                handle dei controlli */
                if(hWin(LIST_A) == NULLHANDLE)
                    GetWindows(hWnd);
                
                /* ottiene le nuove dimensioni della finestra e sposta i 
                controlli */
            	WndSize.x=SHORT1FROMMP(mParam2);
                WndSize.y=SHORT2FROMMP(mParam2);
                SetWndPositions(WndSize,swpFlags);
            }
            break;
            
        /* la finestra deve essere ridisegnata */
        case WM_PAINT:
            {
                HPS		hPS;
                
                /* Ottiene l'handle di una PS e il rettangolo da aggiornare */
                hPS=WinBeginPaint(hWnd,NULLHANDLE,&rect);
                /* Colora la finestra di grigio */
                WinFillRect(hPS,&rect,CLR_PALEGRAY);
                /* fine */
                WinEndPaint(hPS);
            }
            break;
            
        /* Esegue un comando */
        case WM_COMMAND:
            DoCommand(SHORT1FROMMP(mParam1),hWnd);
            break;
            
        /* La finestra e` stata minimizzata o massimizzata */
        case WM_MINMAXFRAME:
            {
                PSWP            pSwp;
                
                pSwp=(PSWP)PVOIDFROMMP(mParam1);
                /* Nel caso che la finestra venga disattivata o ridotta al
                 minimo si nasconde tutto */
                if(pSwp->fl & (SWP_MINIMIZE | SWP_DEACTIVATE))
                    swpFlags=SWP_HIDE;
                else
                    swpFlags=SWP_SHOW;
            }
            break;
            
        /* Aggiorna lo stato di visibilita` della finestra */
        case WM_SHOW:
            {
            	if( SHORT1FROMMP(mParam1) == FALSE )
            		swpFlags=SWP_HIDE;
            	else
                    swpFlags=SWP_SHOW;
            }
            break;
            
        /* Il thread di apertura ha ottenuto un nuovo filename */
        case WM_FILENAME:
            {
                switch((int)mParam1)
                {
                    /* Riguarda il profilo A */
                    case PROFILE_A:
                        /* cancella il vecchio filename e lo sostituisce 
                           con il nuovo */
                        MemFree(PrfA.FileName);
                        PrfA.FileName=(PSZ)mParam2;
                        WinSetWindowText(hWin(EF_FILENAME_A),PrfA.FileName);
                        break;
                        
                    case PROFILE_B:
                        MemFree(PrfB.FileName);
                        PrfB.FileName=(PSZ)mParam2;
                        WinSetWindowText(hWin(EF_FILENAME_B),PrfB.FileName);
                        break;
                        
                    /* Si e` verificato un errore o non e` stato selezionato
                       alcun filename */
                    case FAILURE:
                        {
                            HWND    hButton;
                            
                        	switch((int)mParam2)
                            {
                                /* Riguarda il profilo A */
                                case PROFILE_A:
                                    /* Si ripristina lo stato e si seleziona
                                    il bottone da riabilitare */
                                    PrfA.Status=closed;
                                    hButton=hWin(PB_OPEN_A);
                                    break;
                                    
                            	case PROFILE_B:
                                    PrfB.Status=closed;
                                    hButton=hWin(PB_OPEN_B);
                                	break;
                            }
                            /* Abilita il bottone */
                            WinEnableWindow(hButton,TRUE);
                        }
                        break;
                        
                        /* Questa situazione non si deve mai verificare */
                    default:
                        break;
                }
            }
            break;
            
        /* E` stato aperto con successo un nuovo profilo */
        case WM_PROFILE:
            {
                /* ottiene la struttura di apertura */
                PrfOpen *pOpen=(PrfOpen *)mParam2;
                
                switch((int)mParam1)
                {
                    /* riguarda il profilo A */
                    case PROFILE_A:
                        /* Apre il profilo e ne salva l'handle */
                        PrfA.hProfile=PrfOpenProfile(habMainThread,
                                                     PrfA.FileName);
                        /* Salva la testa della lista delle sezioni */
                        PrfA.List=pOpen->List;
                        /* Il profilo e` aperto */
                        PrfA.Status=opened;
                        /* Aggiorna il bottonie */
                		WinSetWindowText(hWin(PB_OPEN_A),"Close");
                		WinEnableWindow(hWin(PB_OPEN_A),TRUE);
                        break;
                        
                    case PROFILE_B:
                        PrfB.hProfile=PrfOpenProfile(habMainThread,
                                                     PrfB.FileName);
                        PrfB.List=pOpen->List;
                        PrfB.Status=opened;
                		WinSetWindowText(hWin(PB_OPEN_B),"Close");
                		WinEnableWindow(hWin(PB_OPEN_B),TRUE);
                        break;
                        
                    /* In realta` si e` verificato un errore !! */
                    case FAILURE:
                        /* riabilita i botoni e suona un allarme */
                		WinEnableWindow(hWin(PB_OPEN_A),TRUE);
                        WinEnableWindow(hWin(PB_OPEN_B),TRUE);
                        WinAlarm(HWND_DESKTOP,WA_ERROR);
                        
                    default:
                        break;
                }
            }
            break;
            
        /* Un profilo e` stato chiuso con successo */
        case WM_PROFILECLOSED:
            {
                
                switch((int)mParam1)
                {
                    /* riguarda il profilo A */
                    case PROFILE_A:
                        /* Aggiorna il testo del bottone */
                        WinSetWindowText(hWin(PB_OPEN_A),"Open");
                        /* cancella il filename */
                        WinSetWindowText(hWin(EF_FILENAME_A),NULL);
                        /* Aggiorna lo stato e abilita il bottone */
                        PrfA.Status=closed;
                		WinEnableWindow(hWin(PB_OPEN_A),TRUE);
                        break;

                    case PROFILE_B:
                		WinSetWindowText(hWin(PB_OPEN_B),"Open");
                		WinSetWindowText(hWin(EF_FILENAME_B),NULL);
                        PrfB.Status=closed;
                		WinEnableWindow(hWin(PB_OPEN_B),TRUE);
                        break;
                        
                    /* si e` verificato un errore ! */
                    case FAILURE:
                        WinAlarm(HWND_DESKTOP,WA_ERROR);
                        
                    default:
                        break;
                }
            }
            break;
            
        /* Un controllo ha invito un messaggio */
        case WM_CONTROL:
            return DoControl(SHORT2FROMMP(mParam1),SHORT1FROMMP(mParam1),
                             HWNDFROMMP(mParam2));
            break;
            
        /* La finestra e` distrutta e quindi si liberano le risorse */
        case WM_DESTROY:
            FreeResource();
            break;
            
        /* E` stata richiesta la chiusura dell'applicazione */
        case WM_CLOSE:
            {
                QMSG    msg;
                
                /* controllo se il profilo A e` aperto e in caso affermativo
                 lo chiudo */
            	if(PrfA.Status == opened)
                {
                    /* Invio il comando di chiusura simulando la pressione 
                      del bottone */
                    WinPostMsg(hWnd,WM_COMMAND,(MPARAM)PB_OPEN_A,NULL);
                    /* Aspetto che il thread di chiusura si completi facendo 
                    in modo che la coda dei messaggi non venga bloccata */
                    WinGetMsg(habMainThread,&msg,NULLHANDLE,
                              WM_PROFILECLOSED-1,
                              WM_PROFILECLOSED+1);
                    WinDispatchMsg(habMainThread,&msg);
                }
                /* Controllo il profilo B */
            	if(PrfB.Status == opened)
            	{
                	WinPostMsg(hWnd,WM_COMMAND,(MPARAM)PB_OPEN_B,NULL);
                    WinGetMsg(habMainThread,&msg,NULLHANDLE,
                              WM_PROFILECLOSED-1,
                              WM_PROFILECLOSED+1);
                    WinDispatchMsg(habMainThread,&msg);
                }
                /* A questo punto si puo` usire liberamente */
            }
            
        default:
    		return WinDefWindowProc(hWnd,msg,mParam1,mParam2);
    }
    return (MRESULT)FALSE;
}

/* Questa funzione processa i comandi */
void DoCommand(SHORT id,HWND hWnd)
{
    switch(id)
    {
        /* E` stato premuto il bottone del profilo A */
        case PB_OPEN_A:
            /* Controlla lo stato per sapere se deve aprire */
            if(PrfA.Status == closed)
            {
                /* Si crea la styruttura da passare al thread e si riempie */
                PrfA.pthData=(ThreadData *)Memory(sizeof(ThreadData));
                PrfA.Status=opening;
                PrfA.pthData->hWnd=hWnd;
                PrfA.pthData->ListId=LIST_A;
                PrfA.pthData->SubListId=SUBLIST_A;
                PrfA.pthData->Profile=PROFILE_A;
                PrfA.pthData->fName=PrfA.FileName;
                /* Fa pertire il thread di apertura */
                _beginthread((PTHREADFN)OpenThread,NULL,THREAD_STACK,PrfA.pthData);
                /* Disabilita il bottone */
                WinEnableWindow(hWin(PB_OPEN_A),FALSE);
            }
            /* Controlla lo stato per sapere se deve chiudere */
            if(PrfA.Status == opened)
            {
                PrfOpen     *pClose;
                
                /* Crea la struttura da passare al thread e la riempie */
                pClose=(PrfOpen *)Memory(sizeof(PrfOpen));
                PrfA.Status=closing;
                pClose->hWnd=hWnd;
                pClose->Profile=PROFILE_A;
                pClose->List=PrfA.List;
                
                /* Si chiude il profilo e si controlla che non ci siano 
                errori */
                if(!PrfCloseProfile(PrfA.hProfile))
                    ErrorBox(IDE_PRFCLOSE,FALSE);
                
                /* Si resetta la struttura del profilo */
                PrfA.hProfile=NULLHANDLE;
                PrfA.List=NULL;
                
                /* Si fa partire il thread */
                _beginthread((PTHREADFN)CloseThread,NULL,THREAD_STACK,pClose);
                
                /* Si disabilita il bottone */
                WinEnableWindow(hWin(PB_OPEN_A),FALSE);
            }
            break;
            
        /* E` stato premuto il bottone del profilo B */
        case PB_OPEN_B:
            if(PrfB.Status == closed)
            {
                PrfB.pthData=(ThreadData *)Memory(sizeof(ThreadData));
                PrfB.Status=opening;
                PrfB.pthData->hWnd=hWnd;
                PrfB.pthData->ListId=LIST_B;
                PrfB.pthData->SubListId=SUBLIST_B;
                PrfB.pthData->Profile=PROFILE_B;
                PrfB.pthData->fName=PrfB.FileName;
                _beginthread((PTHREADFN)OpenThread,NULL,THREAD_STACK,PrfB.pthData);
                WinEnableWindow(hWin(PB_OPEN_B),FALSE);
            }
            if(PrfB.Status == opened)
            {
                PrfOpen     *pClose;
                
                pClose=(PrfOpen *)Memory(sizeof(PrfOpen));
                PrfB.Status=closing;
                pClose->hWnd=hWnd;
                pClose->Profile=PROFILE_B;
                pClose->List=PrfB.List;
                if(!PrfCloseProfile(PrfB.hProfile))
                    ErrorBox(IDE_PRFCLOSE,FALSE);
                PrfB.hProfile=NULLHANDLE;
                PrfB.List=NULL;
                _beginthread((PTHREADFN)CloseThread,NULL,THREAD_STACK,pClose);
                WinEnableWindow(hWin(PB_OPEN_B),FALSE);
            }
            break;
            
        /* E` stato premuto il bottone di copia da A a B */
        case PB_COPY_AB:
            /* Controlla che ci siano due profili aperti */
            if(PrfA.Status == opened && PrfB.Status == opened)
            {
                SHORT 	AppIndex; /* Posizione nella lista delle applicazioni */
                SHORT   KeyIndex; /* Posizione nella lista delle sottosezioni */
                PSZ     pszApp; /* Nome applicazione */
                PSZ     pszKey; /* Nome sottosezione */
                PrfItem *Head;  /* Puntatore all'applicazione nella lista */
                
                /* Si ottiene l'indice dell'applicazione selezionata */
                AppIndex=(SHORT)WinSendMsg(hWin(LIST_A),LM_QUERYSELECTION,
                                           MPFROMSHORT(LIT_FIRST),NULL);
                /* Se ne ottiene il nome */
                pszApp=StringFromList(hWin(LIST_A),AppIndex);
                
                /* Si cerca se l'applicazione e` gia` presente nella lista
                di destinazione, altrimenti si aggiunge */
               	if((Head=FindItem(PrfB.List,pszApp))==NULL)
                    Head=PrfB.List=AddItem(PrfB.List,pszApp,hWin(LIST_B));
                
                /* Si richiede l'indice della prima selezione della lista
                 delle sottosezioni, se c'e` una selezione si copiano solo
                 gli elementi selezionati altrimenti si copiano tutti */
                if((KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_A),
                                               LM_QUERYSELECTION,
                                               MPFROMSHORT(LIT_FIRST),
                                               NULL)) !=LIT_NONE )
                {
                    /* Ripete il ciclo per ogni elemento selezionato */
                    do 
                    {
                        /* Richiede il nome della sottosezione */
                        pszKey=StringFromList(hWin(SUBLIST_A),KeyIndex);
                        /* Copia i dati */
                        CopyItem(PrfA.hProfile,PrfB.hProfile,pszApp,pszKey);
                        /* Controlla se la sottosezione e` gia presente nella
                        lista di destinazione, in caso negativo si aggiunge */
                    	if(FindSubItem(Head->SubList,pszKey)==NULL)
                            Head->SubList=AddSubItem(Head->SubList,pszKey);
                        /* Libera la memoria del nome */
                        MemFree(pszKey);
                	} while((KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_A),
                                                        LM_QUERYSELECTION,
                                                        MPFROMSHORT(KeyIndex),
                                                        NULL)) != LIT_NONE );
                }
                else
                {
                    /* Non e` stato selezionato niente e quindi si copia
                     tutta l'applicazione. Prima si ottiene il numero di 
                     elementi nella lista */
                    KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_A),
                                               LM_QUERYITEMCOUNT,NULL,NULL);
                    /* Si copiano tutte le sottosezioni */
                    while( KeyIndex-- > 0 )
                    {
                        /* Richiede il nome della sottosezione */
                        pszKey=StringFromList(hWin(SUBLIST_A),KeyIndex);
                        /* Copia i dati */
                        CopyItem(PrfA.hProfile,PrfB.hProfile,pszApp,pszKey);
                        /* Verifica se e` gia` presente nella lista di
                        destinazione, ed eventualmente l'aggiunge */
                    	if(FindSubItem(Head->SubList,pszKey)==NULL)
                            Head->SubList=AddSubItem(Head->SubList,pszKey);
                        /* Libera la memoria del nome */
                    	MemFree(pszKey);
                    }
                }
                /* Ottiene l'indice dell'applicazione nella lista di
                destinazione */
                AppIndex=(SHORT)WinSendMsg(hWin(LIST_B),LM_SEARCHSTRING,
                                           MPFROM2SHORT(LSS_CASESENSITIVE,LIT_FIRST),
                                           (MPARAM)pszApp);
                /* Richiede l'indice della selezione nella lista di
                destinazione */
                KeyIndex=(SHORT)WinSendMsg(hWin(LIST_B),LM_QUERYSELECTION,
                                           MPFROMSHORT(LIT_FIRST),NULL);
                /* Se i due indici differiscono, selezioniamo la nuova 
                applicazione */
                if(AppIndex!=KeyIndex)
                    WinSendMsg(hWin(LIST_B),LM_SELECTITEM,
                               MPFROMSHORT(AppIndex),(MPARAM)TRUE);
                else
                    /* altrimenti era gia` selezionata l'applicazione e 
                    quindi si deve aggiornare solo la sottosezione */
                    FillSubList(hWin(SUBLIST_B),
                                FindItem(PrfB.List,pszApp)->SubList);
                /* Si libera la memoria del nome dell'applicazione */
                MemFree(pszApp);
            }
            else
                /* Non c'era niente di selezionato ! */
                WinAlarm(HWND_DESKTOP,WA_WARNING);
            break;
            
        /* E` stato premuto il bottone di copia da B a A */
        case PB_COPY_BA:
            if(PrfA.Status == opened && PrfB.Status == opened)
            {
                SHORT 	AppIndex;
                SHORT   KeyIndex;
                PSZ     pszApp;
                PSZ     pszKey;
                PrfItem *Head;
                
                AppIndex=(SHORT)WinSendMsg(hWin(LIST_B),LM_QUERYSELECTION,
                                           MPFROMSHORT(LIT_FIRST),NULL);
                pszApp=StringFromList(hWin(LIST_B),AppIndex);
                if((Head=FindItem(PrfA.List,pszApp))==NULL)
                    Head=PrfA.List=AddItem(PrfA.List,pszApp,hWin(LIST_A));
                if((KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_B),
                                               LM_QUERYSELECTION,
                                               MPFROMSHORT(LIT_FIRST),
                                               NULL)) !=LIT_NONE )
                {
                    do 
                    {
                    	pszKey=StringFromList(hWin(SUBLIST_B),KeyIndex);
                    	CopyItem(PrfB.hProfile,PrfA.hProfile,pszApp,pszKey);
                    	if(FindSubItem(Head->SubList,pszKey)==NULL)
                        	Head->SubList=AddSubItem(Head->SubList,pszKey);
                    	MemFree(pszKey);
                	} while((KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_B),
                                                        LM_QUERYSELECTION,
                                                        MPFROMSHORT(KeyIndex),
                                                        NULL)) != LIT_NONE );
                }
                else
                {
                    KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_B),
                                               LM_QUERYITEMCOUNT,NULL,NULL);
                    while( KeyIndex-- > 0 )
                    {
                    	pszKey=StringFromList(hWin(SUBLIST_B),KeyIndex);
                    	CopyItem(PrfB.hProfile,PrfA.hProfile,pszApp,pszKey);
                    	if(FindSubItem(Head->SubList,pszKey)==NULL)
                        	Head->SubList=AddSubItem(Head->SubList,pszKey);
                    	MemFree(pszKey);
                    }
                }
                AppIndex=(SHORT)WinSendMsg(hWin(LIST_A),LM_SEARCHSTRING,
                                           MPFROM2SHORT(LSS_CASESENSITIVE,LIT_FIRST),
                                           (MPARAM)pszApp);
                KeyIndex=(SHORT)WinSendMsg(hWin(LIST_A),LM_QUERYSELECTION,
                                           MPFROMSHORT(LIT_FIRST),NULL);
                if(AppIndex!=KeyIndex)
                    WinSendMsg(hWin(LIST_A),LM_SELECTITEM,
                               MPFROMSHORT(AppIndex),(MPARAM)TRUE);
                else
                    FillSubList(hWin(SUBLIST_A),
                                FindItem(PrfA.List,pszApp)->SubList);
                MemFree(pszApp);
            }
            else
                WinAlarm(HWND_DESKTOP,WA_WARNING);
            break;
            
        /* E` stato premuto il bottone di spostamento da A a B */
        case PB_MOVE_AB:
            /* Controlla che ci siano due profili aperti */
            if(PrfA.Status == opened && PrfB.Status == opened)
            {
                SHORT 	AppIndex; /* Posizione nella lista delle applicazioni */
                SHORT   KeyIndex; /* Posizione nella lista delle sottosezioni */
                PSZ     pszApp; /* Nome applicazione */
                PSZ     pszKey; /* Nome sottosezione */
                PrfItem *Head;  /* Puntatore all'applicazione nella lista */
                PrfItem *AppDel; /* Puntatore all'applicazione da cui si
                                    rimuovono le sezioni */
                
                /* Si ottiene l'indice dell'applicazione selezionata */
                AppIndex=(SHORT)WinSendMsg(hWin(LIST_A),LM_QUERYSELECTION,
                                           MPFROMSHORT(LIT_FIRST),NULL);
                /* Se non e` selezionata alcuna sottosezione si interrompe
                l'operazione */
                if((KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_A),
                                               LM_QUERYSELECTION,
                                               MPFROMSHORT(LIT_FIRST),
                                               NULL)) == LIT_NONE)
                {
                    WinAlarm(HWND_DESKTOP,WA_WARNING);
                    break;
                }
                /* Si ottiene il nome dell'applicazione */
                pszApp=StringFromList(hWin(LIST_A),AppIndex);
                
                /* Si cerca se l'applicazione e` gia` presente nella lista
                di destinazione, altrimenti si aggiunge */
                if((Head=FindItem(PrfB.List,pszApp))==NULL)
                    Head=PrfB.List=AddItem(PrfB.List,pszApp,hWin(LIST_B));
                
                /* Si ricerca l'applicazone da cui si spostano le sezioni per
                poter cancellare dalla lista gli oggetti rimossi */
                AppDel=FindItem(PrfA.List,pszApp);
                
                /* Si ripete il ciclo per ogni sottosezione selezionata */
                do
                {
                    /* Ottiene il nome della sottosezione */
                    pszKey=StringFromList(hWin(SUBLIST_A),KeyIndex);
                    /* Copia i dati */
                    CopyItem(PrfA.hProfile,PrfB.hProfile,pszApp,pszKey);
                    /* Cancella la sezione dal profilo d'origine */
                    PrfWriteProfileData(PrfA.hProfile,pszApp,pszKey,NULL,0);
                    
                    /* Controlla se la sottosezione e` gia presente nella
                    lista di destinazione, in caso negativo si aggiunge */
                    if(FindSubItem(Head->SubList,pszKey)==NULL)
                        Head->SubList=AddSubItem(Head->SubList,pszKey);
                    /* Cancella dalla lista la sottosezione */
                    AppDel->SubList=DeleteSubItem(AppDel->SubList,pszKey,
                                                  hWin(SUBLIST_A));
                    /* Libara la memoria del nome */
                    MemFree(pszKey);
                } while((KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_A),
                                                    LM_QUERYSELECTION,
                                                    MPFROMSHORT(LIT_FIRST),
                                                    NULL)) != LIT_NONE );
                /* Se sono state cancellate tutte le sottosezioni si cancella
                dalla lista anche l'applicazione */
                if(AppDel->SubList == NULL)
                    PrfA.List=DeleteItem(PrfA.List,pszApp,hWin(LIST_A));
                
                /* Si controlla che l'applicazione selezionata non fosse 
                 l'ultima della lista, se lo era si seleziona il nuovo ultimo 
                 elemento */
                KeyIndex=(SHORT)WinSendMsg(hWin(LIST_A),LM_QUERYITEMCOUNT,
                                           NULL,NULL);
                if(AppIndex>=KeyIndex)
                    AppIndex=KeyIndex-1;
                WinSendMsg(hWin(LIST_A),LM_SELECTITEM,
                           MPFROMSHORT(AppIndex),(MPARAM)TRUE);
                
                /* Si ottinene l'indice dell'applicazione nella lista di 
                destinazione */
                AppIndex=(SHORT)WinSendMsg(hWin(LIST_B),LM_SEARCHSTRING,
                                           MPFROM2SHORT(LSS_CASESENSITIVE,LIT_FIRST),
                                           (MPARAM)pszApp);
                
                /* Richiede l'indice della selezione nella lista di
                destinazione */
                KeyIndex=(SHORT)WinSendMsg(hWin(LIST_B),LM_QUERYSELECTION,
                                           MPFROMSHORT(LIT_FIRST),NULL);
                /* Se i due indici differiscono, selezioniamo la nuova 
                applicazione */
                if(AppIndex!=KeyIndex)
                    WinSendMsg(hWin(LIST_B),LM_SELECTITEM,
                               MPFROMSHORT(AppIndex),(MPARAM)TRUE);
                else
                    /* altrimenti era gia` selezionata l'applicazione e 
                    quindi si deve aggiornare solo la sottosezione */
                    FillSubList(hWin(SUBLIST_B),
                                FindItem(PrfB.List,pszApp)->SubList);
                /* si libera la memoria del nome dell'applicazione */
                MemFree(pszApp);
            }
            else
                /* Non e` stat selezionata alcuna sottosezione */
                WinAlarm(HWND_DESKTOP,WA_WARNING);
            break;
            
        /* E` stato premuto il bottone di spostamento da B a A */
        case PB_MOVE_BA:
            if(PrfA.Status == opened && PrfB.Status == opened)
            {
                SHORT 	AppIndex;
                SHORT   KeyIndex;
                PSZ     pszApp;
                PSZ     pszKey;
                PrfItem *AppDel;
                PrfItem *Head;
                
                AppIndex=(SHORT)WinSendMsg(hWin(LIST_B),LM_QUERYSELECTION,
                                           MPFROMSHORT(LIT_FIRST),NULL);
                if((KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_B),
                                               LM_QUERYSELECTION,
                                               MPFROMSHORT(LIT_FIRST),
                                               NULL)) == LIT_NONE)
                {
                	WinAlarm(HWND_DESKTOP,WA_WARNING);
                    break;
                }
                pszApp=StringFromList(hWin(LIST_B),AppIndex);
                if((Head=FindItem(PrfA.List,pszApp))==NULL)
                    Head=PrfA.List=AddItem(PrfA.List,pszApp,hWin(LIST_A));
                AppDel=FindItem(PrfB.List,pszApp);
                do
                {
                    pszKey=StringFromList(hWin(SUBLIST_B),KeyIndex);
                    CopyItem(PrfB.hProfile,PrfA.hProfile,pszApp,pszKey);
                    PrfWriteProfileData(PrfB.hProfile,pszApp,pszKey,NULL,0);
                    if(FindSubItem(Head->SubList,pszKey)==NULL)
                        Head->SubList=AddSubItem(Head->SubList,pszKey);
                    AppDel->SubList=DeleteSubItem(AppDel->SubList,pszKey,
                                                  hWin(SUBLIST_B));
                    MemFree(pszKey);
                } while((KeyIndex=(SHORT)WinSendMsg(hWin(SUBLIST_B),
                                                    LM_QUERYSELECTION,
                                                    MPFROMSHORT(LIT_FIRST),
                                                    NULL)) != LIT_NONE );
                if(AppDel->SubList == NULL)
                    PrfB.List=DeleteItem(PrfB.List,pszApp,hWin(LIST_B));
                KeyIndex=(SHORT)WinSendMsg(hWin(LIST_B),LM_QUERYITEMCOUNT,
                                           NULL,NULL);
                if(AppIndex>=KeyIndex)
                    AppIndex=KeyIndex-1;
                WinSendMsg(hWin(LIST_B),LM_SELECTITEM,
                           MPFROMSHORT(AppIndex),(MPARAM)TRUE);
                
                AppIndex=(SHORT)WinSendMsg(hWin(LIST_A),LM_SEARCHSTRING,
                                           MPFROM2SHORT(LSS_CASESENSITIVE,LIT_FIRST),
                                           (MPARAM)pszApp);
                KeyIndex=(SHORT)WinSendMsg(hWin(LIST_A),LM_QUERYSELECTION,
                                           MPFROMSHORT(LIT_FIRST),NULL);
                if(AppIndex!=KeyIndex)
                    WinSendMsg(hWin(LIST_A),LM_SELECTITEM,
                               MPFROMSHORT(AppIndex),(MPARAM)TRUE);
                else
                    FillSubList(hWin(SUBLIST_A),
                                FindItem(PrfA.List,pszApp)->SubList);
                MemFree(pszApp);
            }
            else
                WinAlarm(HWND_DESKTOP,WA_WARNING);
            break;
            
        /* E` stata selezionata la voce About... nel menu` di sistema */
        case IDM_ABOUT:
            /* Mostra la dialog */
            WinDlgBox(HWND_DESKTOP,hWnd,(PFNWP)AboutWndProc,
                      0,
                      DLG_ABOUTBOX,NULL);
            break;
    }
}

/* Questa funzione copia una sezione da un profilo all'altro */
BOOL CopyItem(HINI Source, HINI Target, PSZ AppName, PSZ KeyName)
{
    BOOL    rc;
    ULONG   Size;  /* dimensione della sezione */
    void    *data; /* puntatore al buffer di memoria */
    
    /* Richiede la dimensione della sezione da copiare */
    rc=PrfQueryProfileSize(Source,AppName,KeyName,&Size);
    /* alloca il buffer di memoria */
    data=Memory(Size);
    /* Legge i dati dal profilo origine e li scrive nel profilo 
    destinazione */
    rc=PrfQueryProfileData(Source,AppName,KeyName,data,&Size);
    rc=PrfWriteProfileData(Target,AppName,KeyName,data,Size);
    /* libera la memoria */
    MemFree(data);
    return TRUE;
}

/* Questa funzione fornisce il testo di un oggetto in una lista una volta
fornito l'handle della lista e l'indice dell'oggetto */
PSZ StringFromList(HWND hWnd,SHORT Index)
{
    SHORT   ItemSize;   /* dimensioni del testo */
    PSZ     String;     /* puntatore al testo */
    
    /* Ottiene prima la lunghezza del testo e ci aggiunge uno */
    ItemSize=(SHORT)WinSendMsg(hWnd,LM_QUERYITEMTEXTLENGTH,
                               (MPARAM)Index,NULL)+1;
    
    /* alloca la memoria per il testo */
    String=(PSZ)Memory(ItemSize);
    /* Richiede il testo */
    WinSendMsg(hWnd,LM_QUERYITEMTEXT,MPFROM2SHORT(Index,ItemSize),String);
    
    /* restituisce la stringa */
    return String;
}

/* Questa funzione esegue i messaggi di notifica inviati dai controlli (in
questo caso dalle ListBox) */
MRESULT DoControl(SHORT code, SHORT id, HWND hControl)

{
    switch(code)
    {
        /* E` stat fatta una nuova selezione in una lista */
        case LN_SELECT:
            {
                SHORT   Index;
                PSZ     Name;
                
                /* Si ottiene l'indice della selezione */
                Index=(SHORT)WinSendMsg(hControl,LM_QUERYSELECTION,
                                        MPFROMSHORT(LIT_FIRST),NULL);
                /* Si distingue tra la lista delle applicazioni del profilo A
                e quella del profilo B */
                switch(id)
                {
                    case LIST_A:
                        {
                            /* Ottengo il testo della selezione */
                            Name=StringFromList(hControl,Index);
                            /* Aggiorno la lista delle sottosezioni */
                            FillSubList(hWin(SUBLIST_A),
                                        FindItem(PrfA.List,Name)->SubList);
                            /* Libero la memoria del tsto */
    						MemFree(Name);
                        }
                        break;
                    case LIST_B:
                        {
    						Name=StringFromList(hControl,Index);
                            FillSubList(hWin(SUBLIST_B),
                                        FindItem(PrfB.List,Name)->SubList);
    						MemFree(Name);
                        }
                        break;
                }
            }
            break;
    }
    return (MRESULT)FALSE;
}

/* Questa funzione carica le risorse contenute nell'eseguibile. In questo 
caso l'unica risorsa e` l'array che contiene le posizioni dei controlli */
void LoadResource(HMODULE hMod)
{
    APIRET      rc;
    
    /* ottiene le risorse e se c'e` un errore mostra un messaggio e 
    termina il programma */
    rc=DosGetResource(hMod,RT_RCDATA,WIN_INICOPIER,(PPVOID)&ChildPos);
    if(rc != NO_ERROR)
        ErrorBox(IDE_INTERNAL,TRUE);
}

/* rilascia le risorse precedentemente richieste */
void FreeResource()
{
    DosFreeResource((PVOID)ChildPos);
}

/* Modifica il menu` di sistema della finestra principale aggiungendoci la
voce "About..." */
void MakeSysMenu(HWND hWnd)
{
   	HWND            hSysMenu; /* Handle del menu` di sistema */
    MENUITEM        mItem;    /* struttura per un elemento del menu` */
    
    /* richiedo l'handle del menu di sistema, se non lo ottengo termino
    il programma */
   	hSysMenu=WinWindowFromID(WinQueryWindow(hWnd,QW_PARENT),FID_SYSMENU);
   	if(hSysMenu==NULLHANDLE)
        ErrorBox(IDE_INTERNAL,TRUE);
    
    /* Ottengo l'handle del menu` a tendina */
    WinSendMsg(hSysMenu,MM_QUERYITEM,
               MPFROM2SHORT(SC_SYSMENU,FALSE),
               MPFROMP(&mItem));
    if(hSysMenu==NULLHANDLE)
    	ErrorBox(IDE_INTERNAL,TRUE);
    hSysMenu=mItem.hwndSubMenu;
    
    /* Riempio la struttura per aggiungere un separatore alla fine del menu`
    a tendina */
    memset(&mItem,0,sizeof(mItem));
    mItem.iPosition=MIT_END;
    mItem.afStyle=MIS_SEPARATOR;
    mItem.id=0xffff;
    /* Aggiungo l'elemento al menu` */
    WinSendMsg(hSysMenu,MM_INSERTITEM,MPFROMP(&mItem),NULL);
    /* Riempio la struttura per aggiunger la voce "About..." */
    mItem.afStyle=MIS_TEXT;
    mItem.id=IDM_ABOUT;
    WinSendMsg(hSysMenu,MM_INSERTITEM,MPFROMP(&mItem),"~About...");
}

/* Aggiorna la posizione e la dimensione dei controlli nella finestra 
principale */
void SetWndPositions(POINTS Size, ULONG show)
{
    SWP     WinPos[NUM_WINS]; /* array di strutture per riposizionare i controlli */
    int     i;
    BOOL    rc;
    
    /* Aggiorno le coordinate virtuali */
    XUnits(Size.x);
    YUnits(Size.y);
    
    /* Riempio l'array di riposizionamento dei controlli */
    /* ChildPos viene caricato dalle risorse ! */
    for(i=0;i<NUM_WINS;i++)
    {
        WinPos[i].fl=SWP_MOVE | SWP_SIZE | show;
        WinPos[i].hwndInsertBehind=HWND_TOP;
        WinPos[i].ulReserved1=WinPos[i].ulReserved2=0;
        /* Calcolo le nuove origini nelle coordinate reali */
        WinPos[i].x=XPoints(ChildPos[i].x);
        WinPos[i].y=YPoints(ChildPos[i].y);
        /* Se una finestra ha coordinate virtuali negative non vengono 
        riscalate, ma solo cambiate di segno */
        WinPos[i].cx=ChildPos[i].dx < 0 ? -ChildPos[i].dx : XPoints(ChildPos[i].dx);
        WinPos[i].cy=ChildPos[i].dy < 0 ? -ChildPos[i].dy : YPoints(ChildPos[i].dy);
        /* Si compila l'handle */
        WinPos[i].hwnd=hChildWnds[i];
    }
    /* riposiziona tutti i controlli insieme, in caso di errore termina il 
    programma*/
    rc=WinSetMultWindowPos(habMainThread,WinPos,NUM_WINS);
    if(rc==FALSE)
        PMErrorBox(habMainThread,TRUE);
}

/* Ottiene gli handle di tutti i controlli */
void GetWindows(HWND hWnd)
{
    LONG    found;
    
    /* Gli ID dei controlli sono scelti tutti contigui in modo da poter 
    riempire l'array degli handle in una sola operazione */
    found=WinMultWindowFromIDs(hWnd,hChildWnds,LIST_A,ST_TEXT_B2);
    if(found!=(ST_TEXT_B2-LIST_A+1))
        PMErrorBox(habMainThread,TRUE);
}


/* fine di main.c */

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

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