/***************************************************************************
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 */
Last modified 27-10-97 |