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

                ProgED V2.x by Giovanni Lambiase (C) 1995-96

                         Note per i programmatori

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


-------------------------
 1. Strutture principali
-------------------------

    Per una breve spiegazione sulle varie strutture e relativi campi
vedi il file PED.h.



------------
 2. Scanner
------------

    Uno scanner deve essere scritto tramite una funzione assembler o una
funzione C che prende gli argomenti nei registri. Il codice risultante
deve essere linkato SENZA alcun modulo di startup, in modo tale che la
prima locazione eseguibile sia l'inizio della funzione scritta. La
funzione di ricerca riceve due argomenti nei seguenti registri:

    A0: Indirizzo della linea su cui effettuare la ricerca. Punta ad una
        stringa terminata con 0.

    A1: Indirizzo del buffer che conterrà il riferimento, se trovato.

    La funzione deve ritornare nel registro D0 la lunghezza della stringa
creata nel buffer puntato da A1. Nel caso la funzione non abbia trovato
nulla deve ritornare 0.

    NOTA: è necessario salvare tutti i registri all'ingresso della
          funzione e ripristarli all'uscita.



-----------
 3. Folder
-----------

    Una funzione di ricerca dei fold deve essere scritta tramite una funzione
assembler o una funzione C che prende gli argomenti nei registri. Il codice
risultante deve essere linkato SENZA alcun modulo di startup, in modo tale
che la prima locazione eseguibile sia l'inizio della funzione scritta. La
funzione di ricerca riceve due argomenti nei seguenti registri:

    A0: è l'indirizzo della struttura PEDWindow relativa al testo su
        cui effettuare la ricerca.

    D0: Contiene il numero della colonna su cui è posizionato il cursore.
        (0=prima colonna).

    D1: Contiene il numero della linea su cui è posizionato il cursore.
        Tale numero è assoluto. Ciò significa che non tiene conto dei
        fold eventualmente presenti nel testo. (0=prima linea).

    A1: Contiene l'indirizzo di una long-word. In tale long-word la funzione
        deve scrivere il numero della linea iniziale del fold, se trovato.
        Anche in questo caso la funzione non deve considerare eventuali
        fold già presenti nel testo. (0=prima linea).

    A2: Contiene l'indirizzo di una long-word. In tale long-word la funzione
        deve scrivere il numero della linea finale del fold, se trovato.
        Anche in questo caso la funzione non deve considerare eventuali
        fold già presenti nel testo. (0=prima linea).

    A3: Punta ad un buffer in cui la funzione deve scrivere la stringa
        che ProgED scriverà a fianco dell'indicatore ">FOLD". Generalmente
        il nome della funzione C, ecc.

    La funzione deve ritornare in D0 il valore 1 se ha trovato un fold, 0
altrimenti. Nel primo caso la funzione deve anche fornire, tramite A1 e A2
i numeri di linea iniziali e finali del fold e, tramite A3, la stringa
rappresentante il fold. è necessario,infine, salvare tutti i registri
all'ingresso della funzione e ripristinarli all'uscita.

    NOTA: la funzione 'FOLD ALL' viene eseguita eseguendo una chiamata
alla funzione su tutte le linee (dalla prima all'ultima) e con il
numero di colonna pari a 0 (prima colonna).



----------------
 4. Clienti API
----------------

    ProgED consente ad applicazioni esterne (chiamate "clienti") di
 "agganciarsi" ad esso. Un cliente API è semplicemente un normale
programma (scritto in qualsiasi linguaggio). Tale programma deve
essere scritto in modo tale da "registrarsi" presso il ProgED. Ciò
consente al ProgED di tracciare tutti i clienti e di mandar loro
messaggi sulle operazioni che devono effettuare.

I messaggi che un cliente deve inviare a ProgED (nella sua porta
API di nome "PED_API") hannno la seguente struttura:



    struct APIMessage
    {
        struct Message     am_Message;
        ULONG              am_MsgType,
                           am_MsgArg[10],
                           am_RC;
    }

    am_Message:

         è un campo contenente un messaggio standard Exec.

    am_MsgType:

         Contiene il tipo di messaggio da inviare.

    am_MsgArg[]:

         è un vettore contenente un massimo di 10 argomenti
         dipendenti dal tipo del messaggio

    am_RC:

         è il codice di ritorno che ProgED restituisce al cliente
         per informarlo sul successo dell'operazione.




    I tipi di messaggi che un cliente può spedire a ProgED sono, per ora:

    PED_API_REGISTER:

          Registra un cliente presso ProgED. Richiede un puntatore ad una
          struttura di tipo APIClient in am_MsgArg[0]. Non ritorna nessun
          risultato in am_RC.

    PED_API_UNREGISTER:

          Informa ProgED che il cliente vuole andarsene (!?). Richiede lo
          STESSO puntatore dato al momento della registrazione, con il
          messaggio PED_API_REGISTER, in am_MsgArg[0]. Non ritorna nessun
          risultato in am_RC.

    PED_API_ADD_INTERNAL_COMMAND:

          Consente di espandere le funzionalità del ProgED aggiungendo un
          nuovo comando interno. A tale scopo è necessario allocare e
          riempire una struttura ArexxExtCmds e fornire il suo puntatore
          in am_MsgArg[0]. Nessun risultato in am_RC.

    PED_API_REM_INTERNAL_COMMAND:

          Rimuove un comando precedentemente aggiunto tramite il messaggio
          PED_API_ADD_INTERNAL_COMMAND. è necessario fornire in am_MsgArg[0]
          lo STESSO puntatore dato al momento dell'aggiunta del comando.
          Non ritorna risultati in am_RC.

    PED_API_GET_ACTIVE_WINDOW:

        Ottiene, in am_RC, l'indirizzo della struttura PEDWindow associata
        alla finestra attualmente attiva.

    PED_API_GET_WINDOW_LIST:

        Ottiene, in am_RC, l'indirizzo iniziale della lista di strutture
        PEDWindow corrispondenti ai testi in memoria.

    PED_GET_SCREEN_ADDRESS:

        Ottiene, in am_RC, l'indirizzo dello schermo del ProgED. Se il ProgED
        è attualmente iconificato ritorna NULL.

    PED_GET_PREFS_ADDRESS:

        Ottiene, in am_RC, l'indirizzo della struttura Prefs.

    PED_GET_PUBSCRNAME:

        Ottiene, in am_RC, un puntatore al nome dello schermo pubblico
        aperto dal ProgED.

    NOTA: La struttura ArexxExtCmds (e tutti gli oggetti a cui puntano i
          suoi campi), fornita al momento dell'aggiunta del comando, deve
          rimanere valida in memoria. è possibile riutilizzarla (o
          liberare la memoria associata solo DOPO aver utilizzato un
          messaggio di tipo PED_REM_INTERNAL_COMMAND.
          Lo stesso vale per la struttura APIClient utilizzata per il
          messaggio PED_API_ADD_INTERNAL_COMMAND. In questo caso è
          possibile riutilizzare la struttura dopo il corrispondente
          messaggio PED_API_REM_INTERNAL_COMMAND.




    I messaggi che ProgED può inviare ad un cliente sono, per ora:

    PED_API_SHOW:

        ProgED ha riaperto il suo schermo. L'indirizzo dello schermo
        può essere ottenuto nel campo am_MsgArg[0]. Nel campo am_MsgArg[1],
        invece, si trova un puntatore al nome dello schermo pubblico
        utilizzato. Il cliente puo' utilizzare queste due informazioni
        per aprire eventuali finestre sullo schermo del ProgED. Questo
        messaggio viene spedito solo se, al momento della registrazione,
        il cliente ha settato il flag NOTIFY_ON_SHOWHIDE.

    PED_API_HIDE:

        ProgED stà per chiudere il suo schermo. Questo messaggio viene
        spedito solo se, al momento della registrazione, il cliente ha
        settato il flag NOTIFY_ON_SHOWHIDE.


    PED_API_KEY:

        L'utente ha battuto un tasto. Il cliente può ottenere la struttura
        IntuiMessage relativa leggendo il campo am_MsgArg[0]. Tale campo
        conterrà il puntatore alla struttura IntuiMessage contenente il
        messaggio di tipo RAWKEY ricevuto dal ProgED. Nel campo am_MsgArg[1],
	invece, il cliente può leggere l'indirizzo della struttura
        PEDWindow associata alla finestra che ha ricevuto il messaggio.
	Questo messaggio viene spedito solo se, al momento della registrazione,
        il cliente ha settato il flag NOTIFY_ON_KEY.

        NOTA: In ogni caso, al termine della gestione di questo messaggio,
        ProgED eseguirà l'azione legata al tasto. Inoltre il cliente
        NON DEVE modificare il messaggio stesso, perchè è un messaggio
        proveniente da Intuition!

    PED_API_QUIT:

        ProgED sta per terminare. Alla ricezione di questo messaggio (che
        viene SEMPRE inviato a prescindere dai flag NOTIFY_xxx) il cliente
        deve chiudere le eventuali finestre e terminare. E' VIETATO
        UTILIZZARE LA PORTA API DOPO LA RICEZIONE DI QUESTO MESSAGGIO !!!!!
        Questo implica che, dopo la ricezione di questo messaggio, il
        cliente NON DEVE tentare di togliere la registrazione e/o la
        definizione di comandi esterni.



    Qui di seguito sono riportate le spiegazioni riguardanti i campi delle
diverse strutture utilizzate.


    struct APIClient
    {
        struct MsgPort          *ac_ClientPort;
        ULONG                    ac_Notify;
        char                    *ac_name;
        struct APIClient        *ac_Next;
    }

    ac_ClientPort:

        Indica l'indirizzo di una porta messaggi a cui ProgED invierà i
        messaggi informativi al cliente. Questo tipo di messaggi verrà
        spiegato successivamente.

    ac_Notify:

        Indica quali tipi di messaggi il cliente vuole ricevere dal ProgED.
        Gli unici tipi di messaggi selezionabili attualmente sono indicati
        dal flag NOTIFY_ON_SHOW_HIDE. 

    ac_Name:

        Punta al nome del cliente.

    ac_Next:

        Porre a NULL. Conterrà il successore cliente della lista interna
        del ProgED.




    struct ArexxExtCmds
    {
        UBYTE                    External;
        char                    *Name;
        char                    *Template;
        void                    *Defaults[MAXREXXARGS];
        LONG ASM                (*CommFunc)( RG(a0) struct CommandData *);
        struct ArexxExtCmds     *NextCmd;
    }

    External:

        Indica che il comando è gestito da un cliente. Porre SEMPRE a TRUE.

    Name:

        Nome del comando. Specificare sempre in lettere maiuscole.

    Template:

        è il template AmigaDOS del comando.

    Default[]:

        Indica il vettore di puntatori che deve essere passato alla
        funzione ReadArgs della dos.library. Deve contenere i valori
        di default dei parametri del template. Per ulteriori informazioni
        leggere la documentazione della funzione ReadArgs.

    CommFunc:

        Indica il puntatore alla funzione che realizza il comando. Tale
        funzione deve essere scritta in assembler (o ricevere i parametri
        come una funzione assembler). Essa deve ricevere un puntatore ad
        una struttura CommandData in A0 e ritornare il codice d'errore
        risultante dall'esecuzione in D0. In seguito analizzeremo la
        struttura CommandData.

    NextCmd:

        Porre a NULL. ProgED ne modificherà il valore portandolo a
        puntare al prossimo comando fornito dallo stesso cliente o da
        un altro.




    struct CommandData
    {
        char              *CommandLine;
        void             **CommandArgs;
        struct MyWindow   *CurrentWindow,
                          *FirstWindow;
        struct Prefs      *CurrentPrefs;
        LONG ASM (*ExecuteInternalCommand)(RG(a0) char *);
    }

    CommandLine:

        Punta ad una stringa riportante l'intera linea di comando riguardante
        il comando.

    CommandArgs:

        Punta ad un vettore di (void *). Ogni puntatore deve essere utilizzato
        secondo le norme dettate dalla ReadArgs. Questo vettore, infatti, è
        il risultato della applicazione della stessa funzione alla linea di
        comando (tenendo presente i default dati nella struttura ArexxExtCmds).

    CurrentWindow:

        Indica il puntatore alla struttura PEDWindow indicante la finestra
        attualmente attiva.

    FirstWindow:

        Indica il puntatore alla prima struttura PEDWindow della lista di
        finestre mantenuta dal ProgED.

    CurrentPrefs:

	Punta ad una struttura Prefs contenente le preferenze attuali.

    ExecuteInternalCommand:

        è un puntatore ad una funzione assembler. Chiamando questa
        funzione (specificando in A0 il puntatore ad una stringa) è
        possibile eseguire i comandi interni del ProgED. A tale scopo
        la stringa puntata da A0 deve contenere la linea di comando
        desiderata. In D0 viene ritornato il codice d'errore risultante.

        NOTA: Non utilizzare la porta ARexx di ProgED per eseguire i
        comandi interni! Così facendo, infatti, si bloccherebbero
        sia ProgED che il cliente. Ciò è dovuto al fatto che, mentre
        ProgED esegue la funzione che implementa il comando, NON PUò
        rispondere ai messaggi provenienti da sè stesso!



-------------------
 5. Funzioni utili
-------------------

    Le funzioni C che seguono sono utili per la scrittura di folder e
scanner. Esse riguardano la ricerca di linee. Potete utilizzarle
tagliandole da questo testo e inserendole nei vostri programmi.



/*****
 *
 * FUNZIONE:	struct Line *SearchLine(struct Line *line,int y)
 *
 * SCOPO:	Cerca l'indirizzo della linea "y-esima" (0=prima) a partire
 *		dalla prima linea del file data da line.
 *		NB: Tiene conto dei FOLDS.
 *
 * RESTITUISCE: Un puntatore alla linea cercata.
 *
 ****/

struct Line *SearchLine(struct Line *line,int y)
{
	while(((y--)>0)&&(line))	line=NextLine(line);
	return(line);
}



/*****
 *
 * FUNZIONE:	int SearchLine2(struct Line *line,int y)
 *
 * SCOPO:	Cerca il # della linea (tenendo conto dei FOLD)
 *		della linea ASSOLUTA y.
 *
 * RESTITUISCE: Il # della linea cercata.
 *
 ****/

int SearchLine2(struct Line *line,int y)
{
	int	n=0;

	while(((y--)>0)&&(line))
	{
		if (!line->Folder)	n++;
		else	if (line->NextLine)
				if (!line->NextLine->Folder)	n++;
		line=line->NextLine;
	}
	if (line)	return(n);
	else		return(0);
}



/*****
 *
 * FUNZIONE:	int SearchLine3(struct Line *first,struct Line *line)
 *
 * SCOPO:	Cerca il # assoluto della linea line a partire
 *		dalla prima linea del file data da first.
 *		NB: NON tiene conto dei FOLDS.
 *
 * RESTITUISCE: Il # della linea cercata.
 *
 ****/

int SearchLine3(struct Line *first,struct Line *line)
{
	long	n=0;

	while(first)
	{
		if (first==line)	break;
		n++;
		first=first->NextLine;
	}
	return(n);
}



/*****
 *
 * FUNZIONE:	struct Line *SearchLine4(struct Line *line,int y)
 *
 * SCOPO:	Cerca l'indirizzo della linea "y-esima" (0=prima) a partire
 *		dalla prima linea del file data da line.
 *		NB: NON tiene conto dei FOLDS.
 *
 * RESTITUISCE: Un puntatore alla linea cercata.
 *
 ****/

struct Line *SearchLine4(struct Line *line,int y)
{
	while(((y--)>0)&&(line))	line=line->NextLine;
	return(line);
}



