Obligement - L'Amiga au maximum

Mercredi 13 décembre 2017 - 23:49  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Hit Parade
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles in other languages


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Moteurs de recherche
 · Pages de liens
 · Constructeurs matériels
 · Matériel
 · Autres sites de matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Développeurs logiciels
 · Logiciels
 · Développeurs de jeux
 · Jeux
 · Autres sites de jeux
 · Scène démo
 · Divers
 · Informatique générale


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : Assembleur - un programme multifenêtres
(Article écrit par Frédéric Delacroix et extrait d'Amiga News - septembre 1995)


Il est parfois embêtant, dans une application, de devoir fermer les fenêtres de service pour pouvoir utiliser la fenêtre principale. La mode est au contraire aux applications dans lesquelles de multiples fenêtres peuvent être ouvertes indépendamment les unes des autres.

Pièges

Il s'agit d'un problème assez délicat, en assembleur comme dans d'autres langages. La première chose à laquelle on peut penser est la création d'un nouveau processus pour chaque fenêtre. Derrière la simplicité apparente de cette solution (surtout avec CreateNewProc() et consorts) se cachent d'autres problèmes très méchants, comme la communication entre tâches et l'arbitrage des ressources, sans parler de la tuerie nécessaire lorsque le programme veut quitter...

D'un autre côté, il y a la solution, potentiellement moins puissante (ce qui est loin d'être évident) de la gestion de toutes ces fenêtres par le seul processus principal, beaucoup plus simple au niveau programmation. Il y a toutefois de quoi se perdre si on s'y prend mal. La solution que je vous décris dans cet article a le mérite de marcher et d'être très extensible, même si ce n'est pas forcément la plus simple. Vous pourrez sans peine rajouter un nombre quelconque de fenêtres et de messages à traiter.

Dans cette solution, il peut arriver des problèmes lorsqu'on a plus de 16 fenêtres ouvertes utilisant l'IDCMP en même temps. En effet, lorsque les drapeaux IDCMP d'une fenêtre que l'on ouvre ne sont pas nuls, Intuition alloue et initialise le UserPort (le champ wd_UserPort est nul sinon, voir l'autodoc de ModifyIDCMP()). La meilleure solution est alors d'utiliser une solution dans laquelle les différentes fenêtres partagent le même port IDCMP, le champ im_IDCMPWindow de la structure IntuiMessage permettant d'identifier la fenêtre émettrice ; cette solution est d'ailleurs utilisée par les requêtes de l'asl.library. Nous examinerons peut-être cette solution dans un prochain article.

Principe

Il faut être convaincu de la nécessité de penser "structure", même si on est en assembleur. Une fenêtre est modélisée par une structure, décrite au début du code source, qui contient plein d'informations importantes comme l'adresse de la structure Window si elle est ouverte, l'adresse des routines à appeler lors d'événements comme le rafraîchissement ou l'action sur un gadget.

Une routine se charge alors d'ouvrir une fenêtre, une autre de la fermer, en prenant bien garde de toujours actualiser la structure en question pour que d'autres parties du programme n'accèdent pas à des informations obsolètes (on croit toujours avoir prévu tous les cas...).

Vient ensuite la routine centrale, qui se charge d'attendre un signal d'une fenêtre, de récupérer et d'interpréter tous les messages de cette fenêtre ; le tout dans une boucle prévoyant le cas où plusieurs fenêtres se manifestent en même temps (ne croyez pas que ce soit impossible : ça m'est arrivé en mode trace avec Monam).

Il ne faut pas vous laisser décourager par la complexité (encore que...) de l'algorithme ; il est évident qu'on ne le "pond" pas tel quel en une seule passe. Pour ce genre de choses, il y a toujours une partie débogage intense.

Exemple

Le programme d'exemple que je vous propose ne sert pas à grand-chose et est loin d'être terminé. Il s'agit d'un lecteur de fichier extrêmement rudimentaire (limité aux 128 premiers octets) en ASCII et hexa. Pour l'instant (faute de place), seule la partie ASCII fonctionne, mais vous pouvez quand même jouer avec l'ouverture des fenêtres, et remarquer qu'elles sont indépendantes les unes des autres.

Comme vous pourrez le constater, j'ai négligé les possibilités d'optimisation du programme au profit de l'extensibilité de l'algorithme ; il vous sera facile, si vous avez compris le principe, d'étendre ses fonctionnalités. N'ayant pas Amiga News pour moi tout seul, je vous renvoie au code source et à ses commentaires pour de plus amples informations, ainsi qu'à Amiga News n°77 pour tout ce qui concerne l'interface GadTools de la fenêtre principale (j'ai juste enlevé la gestion des polices de caractères autres que topaz/8).

    include exec/exec.i
    include exec/exec_lib.i
    include intuition/intuition.i
    include intuition/intuition_lib.i
    include libraries/gadtools.i
    include libraries/gadtools_lib.i
    include graphics/gfx.i
    include graphics/graphics_lib.i

; structure regroupant les informations relatives à une
; fenêtre: tags, struct Window, routines diverses...
    STRUCTURE   WindowStruct,0
     APTR   ws_Next
     APTR   ws_Window
     APTR   ws_UserPort
     ULONG  ws_SigMask
     APTR   ws_Tags
     APTR   ws_PreOpen
     APTR   ws_PostOpen
     APTR   ws_PreClose
     APTR   ws_PostClose
     APTR   ws_CloseWindow
     APTR   ws_MouseButtons
     APTR   ws_Render
     UBYTE  ws_Flags
     UBYTE  ws_SigBit
    LABEL   ws_SIZEOF

; le flag suivant indique que la fenêtre utilise la
; gadtools.library (filtrage des message, 
; rafraîchissement...)

    BITDEF  WS,USEGADTOOLS,0

        move.l  4.w,a6
        move.l  ThisTask(a6),a4
        tst.l   pr_CLI(a4)
        bne.s   FromCLI
        lea     pr_ MsgPort(a4),a0
        jsr     _LVOWaitPort(a6)
        lea     pr_MsgPort(a4),a0
        jsr     _LVOGetMsg(a6)
        move.l  d0,WB.Startup
FromCLI lea Intuition.Name(pc),a1
        moveq   #37,d0
        jsr     _LVOOpenLibrary(a6)
        move.l  d0,Intuition.Base
        beq     exit
        lea     GadTools.Name(pc),a1
        moveq   #37,d0
        jsr     _LVOOpenLibrary(a6)
        move.l  d0,GadTools.Base
        beq.s   CloseIntuition
        lea     DOS.Name(pc),a1
        moveq   #37,d0
        jsr     _LVOOpenLibrary(a6)
        move.l  d0,DOS.Base
        beq.s   CloseGadTools
        lea     Graphics.Name(pc),a1
        moveq   #37,d0
        jsr     _LVOOpenLibrary(a6)
        move.l  d0,Graphics.Base
        beq.s   CloseDOS
; ce programme ne prévoit que  l'utilisation 
; de topaz/8
        lea     Topaz.TextAttr(pc),a0
        move.l  d0,a6
        jsr     _LVOOpenFont(a6)
        move.l  d0,Topaz.TextFont
        beq.s   CloseGraphics

; ouvre la fenêtre principale
        lea     MainWin.Struct(pc),a0
        bsr.s   OpenAWindow
        beq.s   MainFailed
        bsr     Load.Routine
        bsr     ProcessMessages
MainFailed

CloseTopaz
        move.l  Graphics.Base(pc),a6
        move.l  Topaz.TextFont(pc),a1
        jsr     _LVOCloseFont(a6)
CloseGraphics
        move.l  Graphics.Base(pc),a1
        move.l  4.w,a6
        jsr     _LVOCloseLibrary(a6)
CloseDOS
        move.l  DOS.Base(pc),a1
        jsr     _LVOCloseLibrary(a6)
CloseGadTools
        move.l  GadTools.Base(pc),a1
        jsr     _LVOCloseLibrary(a6)
CloseIntuition
        move.l  Intuition.Base(pc),a1
        jsr     _LVOCloseLibrary(a6)
exit    move.l  WB.Startup(pc),d0
        beq.s   ToCLI
        move.l  d0,a1
        jsr     _LVOForbid(a6)
        jsr     _LVOReplyMsg(a6)
ToCLI   moveq   #0,d0
        rts

; la routine suivante sert à ouvrir une fenêtre 
; identifiée par sa structure. Elle se charge
; d'appeler la routine PreOpen avant 
; l'ouverture (par ex. pour la création de
; gadgets) et PostOpen après (pour un dessin par ex.)
; Si l'ouverture échoue, cette routine appelle PostClose
; pour libérer les ressources allouées par PreOpen

OpenAWindow
  ; (Z=0)Success=OpenAWindow(WindowStruct)(A0)
        movem.l a2/a6,-(sp)
        move.l  a0,a2
        move.l  ws_PreOpen(a2),d0
        beq.s   .NoPreOpen
        move.l  d0,a0
        jsr     (a0)
        beq.s   .Failed
.NoPreOpen
        suba.l  a0,a0
        move.l  ws_Tags(a2),a1
        move.l  Intuition.Base(pc),a6
        jsr     _LVOOpenWindowTagList(a6)
        move.l  d0,ws_Window(a2)
        beq.s   .NoWindow
        move.l  d0,a0
        move.l  wd_UserPort(a0),a0
        move.l  a0,ws_UserPort(a2)
        moveq   #1,d0
        moveq   #0,d1
        move.b  MP_SIGBIT(a0),d1
        move.b  d1,ws_SigBit(a2)
        lsl.l   d1,d0
        move.l  d0,ws_SigMask(a2)
        move.l  ws_PostOpen(a2),d0
        beq.s   .Success
        move.l  d0,a0
        jsr     (a0)
        bne.s   .Success
        move.l  ws_Window(a2),a0
        jsr     _LVOCloseWindow(a6)
.NoWindow
        move.l  ws_PostClose(a2),d0
        beq.s   .Failed
        move.l  d0,a0
        jsr     (a0)
.Failed clr.l   ws_Window(a2)
        clr.l   ws_UserPort(a2)
        clr.l   ws_SigMask(a2)
.Success
        move.l  ws_Window(a2),d0    
                        ; positionner Z
        movem.l (sp)+,a2/a6
        rts

; la routine suivante ferme une fenêtre. Il faut prendre
; garde à bien effacer les variables devenues obsolètes:
; ws_Window, ws_UserPort... Elle appelle PreClose
; avant la fermeture et PostClose après.
CloseAWindow
        ; CloseAWindow(WindowStruct)(A0)
        movem.l a2/a6,-(sp)
        tst.l   ws_Window(a0)
        beq.s   .NoWin
        move.l  a0,a2
        move.l  ws_PreClose(a2),d0
        beq.s   .NoPreClose
        move.l  d0,a0
        jsr     (a0)
.NoPreClose
        move.l  ws_Window(a2),a0
        move.l  Intuition.Base(pc),a6
        jsr     _LVOCloseWindow(a6)
        clr.l   ws_Window(a2)
        clr.l   ws_SigMask(a2)
        clr.l   ws_UserPort(a2)
        clr.b   ws_SigBit(a2)
        move.l  ws_PostClose(a2),d0
        beq.s   .NoPostClose
        move.l  d0,a0
        jsr     (a0)
.NoPostClose
.NoWin  movem.l (sp)+,a2/a6
        rts

SetScreen   ; (Z=0)Success=SetScreen()
        movem.l d0-d1/a1/a6,-(sp)
        move.l  Intuition.Base(pc),a6
        suba.l  a0,a0
        jsr     _LVOLockPubScreen(a6)
        move.l  d0,a0
        move.l  a0,Locked.Screen
        beq.s   .Ret
        suba.l  a1,a1
        move.l  GadTools.Base(pc),a6
        jsr     _LVOGetVisualInfoA(a6)
        move.l  d0,Screen.VisualInfo
        bne.s   .Ret
        move.l  Intuition.Base(pc),a6
        suba.l  a0,a0
        move.l  Locked.Screen(pc),a1
        jsr     _LVOUnlockPubScreen(a6)
        clr.l   Locked.Screen
.Ret    movem.l (sp)+,d0-d1/a1/a6
        rts

UnsetScreen
        move.l  a6,-(sp)
        move.l  Screen.VisualInfo(pc),a0
        move.l  GadTools.Base(pc),a6
        jsr     _LVOFreeVisualInfo(a6)
        clr.l   Screen.VisualInfo
        suba.l  a0,a0
        move.l  Locked.Screen(pc),a1
        move.l  Intuition.Base(pc),a6
        jsr     _LVOUnlockPubScreen(a6)
        rts

; routine PreOpen de la fenêtre principale. 
; Il s'agit principalement de la création de 
; gadgets gadtools, Cf. Amiga News N°77

MainWin.PreOpen 
 ; (Z=0)Success=PreOpen(WindowStruct)(A2)
        movem.l d2-d4/a2-a6,-(sp)
        bsr     SetScreen
        beq     .Failed
        move.l  Locked.Screen(pc),a0
        moveq   #0,d3
        move.l  d3,d2
        move.b  sc_WBorLeft(a0),d2
        move.l  sc_Font(a0),a1
        move.w  ta_YSize(a1),d3
        addq.w  #1,d3
        add.b   sc_WBorTop(a0),d3
        lea     MainWin.GList(pc),a0
        move.l  GadTools.Base(pc),a6
        jsr     _LVOCreateContext(a6)
        move.l  d0,a3
        beq.s   .NoContext
        lea       MainWin.NewGads(pc),a5
        lea     MainWin.Gads(pc),a4
        moveq   #0,d4
.FillNext
        lea     NewGadget.Struct(pc),a1
        move.w  d4,gng_GadgetID(a1)
.Fill   moveq   #0,d0
        move.l  d0,d1
        move.b  (a5)+,d0
        move.b  (a5)+,d1
        beq.s   .TransferLong
        move.w  (a5)+,0(a1,d0.w)
        cmp.b   #2,d1
        bne.s   .NoD2
        add.w   d2,0(a1,d0.w)
        bra.s   .TransferDone
.NoD2   cmp.b   #3,d1
        bne.s   .TransferDone
        add.w   d3,0(a1,d0.w)
        bra.s   .TransferDone
.TransferLong
        move.l  (a5)+,0(a1,d0.w)
.TransferDone
        cmp.b   #-1,(a5)
        bne.s   .Fill
        addq.l  #1,a5
        moveq   #0,d0
        move.b  (a5)+,d0    ; kind
        move.l  (a5)+,a2    ; tags
        move.l  a3,a0
        jsr     _LVOCreateGadgetA(a6)
        move.l  d0,a3
        move.l  d0,(a4)+
        beq.s   .NoGadget
        addq.w  #1,d4
        cmp.w   #MainWin.GadCnt,d4
        bne.s   .FillNext
        moveq   #-1,d0
.Ret    movem.l (sp)+,d2-d4/a2-a6
        rts
.NoGadget
.NoContext
        move.l  MainWin.GList(pc),a0
        jsr     _LVOFreeGadgets(a6)
        clr.l   MainWin.GList
.Failed moveq   #0,d0
        bra.s   .Ret

; PostOpen de la fenêtre principale.
MainWin.PostOpen    
    ; (Z=0)Success=PostOpen(WindowStruct)(A2)
        move.l  a6,-(sp)
        move.l  ws_Window(a2),a0
        suba.l  a1,a1
        move.l  GadTools.Base(pc),a6
        jsr     _LVOGT_RefreshWindow(a6)
        moveq   #-1,d0
        movea.l (sp)+,a6
        rts

; PostClose de la fenêtre principale
MainWin.PostClose
        move.l  a6,-(sp)
        move.l  MainWin.GList(pc),a0
        move.l  GadTools.Base(pc),a6
        jsr     _LVOFreeGadgets(a6)
        clr.l   MainWin.GList
        move.l  (sp)+,a6
        rts

; pour les fenêtre ascii et hexa, on saute 
; à la routine de dessin
Ascii.PostOpen
Hexa.PostOpen
        move.l  ws_Render(a2),-(sp)
        rts

; routine qui contient la boucle principale
ProcessMessages
    move.l  sp,QuitStack    ; pile pour sortir
ProcessLoop
    lea MainWin.Struct(pc),a0
    moveq   #0,d0
.MakeMask
    or.l    ws_SigMask(a0),d0    ; le masque des
    move.l  ws_Next(a0),d1       ; signaux d'attente 
    movea.l d1,a0       ; est construit par une  
    bne.s   .MakeMask   ; série de OUs logiques.
    move.l  4.w,a6
    jsr     _LVOWait(a6)
    move.l  d0,d7       ; signaux reçus

; trouvons la fenêtre qui se manifeste
    lea     MainWin.Struct(pc),a2
.FindWin
    move.b  ws_SigBit(a2),d0    ; teste si cette
    bclr    d0,d7           ; fenêtre a activé
                    ;  son signal
    bne.s   .WFound
.WinDone
    move.l  ws_Next(a2),d0  ; teste la fenêtre
                    ; suivante
    movea.l d0,a2
    beq     ProcessLoop
    bra     .FindWin
.WFound     ; cette fenêtre a activé 
            ; un signal
.MsgLoop

; il ne faut pas oublier de tester si le port IDCMP existe
; toujours, il se peut que l'action précédente (c'est une
; autre boucle) était de fermer la fenêtre...

    move.l  ws_UserPort(a2),d0
    movea.l d0,a0
    beq     .WinDone
    move.l  4.w,a6
    jsr     _LVOGetMsg(a6)
    clr.l   IM.Class
    move.l  d0,a1
    move.l  a1,d0
    beq     .WinDone
    btst    #WSB_USEGADTOOLS,ws_Flags(a2)
    beq.s   .NoFilter

; les messages de fenêtres utilisant la gadtools.library
; requièrent un filtrage particulier car on n'utilise pas
; GT_GetIMsg() et GT_ReplyIMsg()

    move.l  a1,a3
    move.l  GadTools.Base(pc),a6
    jsr     _LVOGT_FilterIMsg(a6)
    move.l  d0,a1
    move.l  a1,d0
    beq.s   .NoGadMsg
.NoFilter
    move.l  im_Class(a1),IM.Class
    move.w  im_Code(a1),IM.Code
    move.l  im_IAddress(a1),IM.IAddress
    btst    #WSB_USEGADTOOLS,ws_Flags(a2)
    beq.s   .NoPostFilter
    jsr     _LVOGT_PostFilterIMsg(a6)
.NoGadMsg
    move.l  a3,a1
.NoPostFilter
    move.l  4.w,a6
    jsr     _LVOReplyMsg(a6)
    move.w  IM.Code(pc),d1
    move.l  IM.Class(pc),d0
    bne.s   .InterpretMsg
    bra     .MsgLoop

.InterpretMsg
    cmp.l   #IDCMP_REFRESHWINDOW,d0
    bne.s   .NotRefresh

; pour le rafraîchissement, on demande à la fenêtre de
; se rafraîchir en appelant la routine pointée par le
; champ ws_Render de sa structure représentative,
;  après avoir signalé à Intuition (éventuellement en 
; passant par gadtools) le début du rafraîchissement.

    btst    #WSB_USEGADTOOLS,ws_Flags(a2)
    bne.s   .GadToolsRefresh
    move.l  ws_Window(a2),a0
    move.l  Intuition.Base(pc),a6
    jsr     _LVOBeginRefresh(a6)
    move.l  ws_Render(a2),d0
    beq.s   .NoRender
    move.l  d0,a0
    jsr     (a0)
.NoRender
    move.l  ws_Window(a2),a0
    moveq   #-1,d0
    move.l  Intuition.Base(pc),a6
    jsr     _LVOEndRefresh(a6)
    bra     .MsgLoop
.GadToolsRefresh
    move.l  ws_Window(a2),a0
    move.l  GadTools.Base(pc),a6
    jsr     _LVOGT_BeginRefresh(a6)
    move.l  ws_Render(a2),d0
    beq.s   .NoRenderG
    move.l  d0,a0
    jsr     (a0)
.NoRenderG
    move.l  ws_Window(a2),a0
    moveq   #-1,d0
    move.l  GadTools.Base(pc),a6
    jsr     _LVOGT_EndRefresh(a6)
    bra     .MsgLoop

.NotRefresh
    cmp.l   #IDCMP_GADGETUP,d0
    bne.s   .NotGadUp

; pour une action sur un gadget, la routine est
; fournie par le champ gg_UserData d'icelui.

    move.l  IM.IAddress(pc),a1  ; adresse du gadget
    move.l  gg_UserData(a1),d0
    beq     .MsgLoop
    move.l  d0,a0
    jsr     (a0)
    bra     .MsgLoop

.NotGadUp
    cmp.l   #IDCMP_CLOSEWINDOW,d0
    bne.s   .NotCloseW

; en cas d'action sur le bouton de fermeture, on appelle
; la routine pointée par le champ ws_CloseWindow

    move.l  ws_CloseWindow(a2),d0
    beq     .MsgLoop
    move.l  d0,a0
    jsr     (a0)
    bra     .MsgLoop
.NotCloseW
    cmp.l   #IDCMP_MOUSEBUTTONS,d0
    bne     .MsgLoop
    move.l  ws_MouseButtons(a2),d0  ; pareil
    beq     .MsgLoop
    move.l  d0,a0
    jsr     (a0)
    bra     .MsgLoop

; pour la fermeture de la fenêtre principale, on ferme
; toutes les fenêtres et on sort de la routine
; ProcessMesages en restaurant le pointeur de pile
; (magie!)

MainWin.Close
    move.l  QuitStack(pc),sp
    lea     MainWin.Struct(pc),a0
.CloseLoop
    move.l  ws_Next(a0),d2
    bsr     CloseAWindow
    move.l  d2,a0
    move.l  a0,d2
    bne.s   .CloseLoop
    rts

; cette routine charge les 128 premiers octets du
; fichier RAM:File. A améliorer, bien entendu...

Load.Routine
    movem.l d0-d4/a0-a1/a6,-(sp)
    move.l  #File.Name,d1
    move.l  #MODE_OLDFILE,d2
    move.l  DOS.Base(pc),a6
    jsr     _LVOOpen(a6)
    move.l  d0,d4
    beq.s   .Return
    move.l  d4,d1
    move.l  #File.Buffer,d2
    move.l  #File.BufSize,d3
    jsr     _LVORead(a6)
    move.l  d4,d1
    jsr     _LVOClose(a6)
    bsr.s   Ascii.Render
    bsr.s   Hexa.Render
.Return movem.l  (sp)+,d0-d4/a0-a1/a6
    rts

; je laisse ces routines à votre sagacité
Ascii.MouseBut
Hexa.MouseBut
Hexa.Render
OffsetEntered
    rts

; ici, on inverse l'état d'ouverture d'une fenêtre.

Ascii.Close
OpenASCII
    lea     Ascii.Struct(pc),a0
ToggleWin
    tst.l   ws_Window(a0)
    bne     CloseAWindow
    bra     OpenAWindow
Hexa.Close
OpenHexa
    lea     Hexa.Struct(pc),a0
    bra.s   ToggleWin

; La routine suivante dessine les caractères dans
; la fenêtre ASCII avec la fonte topaz/8 (désolé)

Ascii.Render
    movem.l d0-d2/a0-a3/a6,-(sp)
    lea     Ascii.Struct(pc),a2
    move.l  ws_Window(a2),d0
    movea.l d0,a3
    beq.s   .NoWin
    move.l  wd_RPort(a3),a1
    move.l  Topaz.TextFont(pc),a0
    move.l  Graphics.Base(pc),a6
    jsr     _LVOSetFont(a6)
    move.l  wd_RPort(a3),a1
    moveq   #1,d0
    jsr     _LVOSetAPen(a6)
    move.l  wd_RPort(a3),a1
    moveq   #0,d0
    jsr     _LVOSetBPen(a6)
    move.l  wd_RPort(a3),a1
    moveq   #RP_JAM2,d0
    jsr     _LVOSetDrMd(a6)
    moveq   #0,d2
.Loop  moveq    #4,d0
    move.l  wd_WScreen(a3),a0
    add.b   sc_WBorLeft(a0),d0
    move.l  d2,d1
    lsl.l   #3,d1
    add.l   #4+6,d1
    add.b   sc_WBorTop(a0),d1
    addq.b  #1,d1
    move.l  sc_Font(a0),a0
    add.w   ta_YSize(a0),d1
    move.l  wd_RPort(a3),a1
    jsr     _LVOMove(a6)
    lea     File.Buffer,a0
    move.l  d2,d0
    lsl.l   #4,d0
    add.l   d0,a0
    move.l  wd_RPort(a3),a1
    moveq   #16,d0
    jsr     _LVOText(a6)
    addq.l  #1,d2
    cmp.l   #8,d2
    bne.s   .Loop

; avant de sortir, il faut mettre Z à 0
; car cette routine est aussi appelée en PostOpen

    moveq   #-1,d0
.NoWin  movem.l  (sp)+,d0-d2/a0-a3/a6
    rts

MainWin.Struct
    dc.l    Ascii.Struct
    dc.l    0
    dc.l    0
    dc.l    0
    dc.l    MainWin.Tags
    dc.l    MainWin.PreOpen
    dc.l    MainWin.PostOpen
    dc.l    0           ; PreClose
    dc.l    MainWin.PostClose
    dc.l    MainWin.Close
    dc.l    0           ; MouseBut
    dc.l    0           ; Render
    dc.b    WSF_USEGADTOOLS,0

MainWin.Tags
    dc.l    WA_Left,1000
    dc.l    WA_Top,600
    dc.l    WA_InnerWidth,88
    dc.l    WA_InnerHeight,64
    dc.l    WA_IDCMP,IDCMP 
            _REFRESHWINDOW!IDCMP
            _GADGETUP!IDCMP
            _CLOSEWINDOW
    dc.l    WA_Flags,WFLG
            _DRAGBAR!WFLG
            _ DEPTHGADGET!WFLG
            _CLOSEGADGET!WFLG
            _ACTIVATE
    dc.l    WA_Title,MainWin.Title
    dc.l    WA_AutoAdjust,-1
    dc.l    WA_Gadgets

MainWin.GList  dc.l 0
               dc.l TAG_DONE

MainWin.NewGads     ; Cf. Amiga News N°77
    ENUM
    EITEM   ID_LOAD     ; load button
    dc.b    gng_LeftEdge,2
    dc.w    4
    dc.b    gng_TopEdge,3
    dc.w    6
    dc.b    gng_Width,1
    dc.w    80
    dc.b    gng_Height,1
    dc.w    10
    dc.b    gng_GadgetText,0
    dc.l    Load.Label
    dc.b    gng_Flags,0
    dc.l    PLACETEXT_IN
    dc.b    gng_UserData,0
    dc.l    Load.Routine
    dc.b    -1,BUTTON_KIND
    dc.l    LoadBut.Tags

; ascii button
    EITEM   ID_ASCII
    dc.b    gng_TopEdge,3
    dc.w    18
    dc.b    gng_GadgetText,0
    dc.l    ASCII.Label
    dc.b    gng_UserData,0
    dc.l    OpenASCII
    dc.b    -1,BUTTON_KIND
    dc.l    OpenASCII.Tags

; hexa button
    EITEM   ID_HEXA
    dc.b    gng_TopEdge,3
    dc.w    30
    dc.b    gng_GadgetText,0
    dc.l    Hexa.Label
    dc.b    gng_UserData,0
    dc.l    OpenHexa
    dc.b    -1,BUTTON_KIND
    dc.l    OpenHexa.Tags

; offset integer
    EITEM   ID_OFFSET
    dc.b    gng_LeftEdge,2
    dc.w    60
    dc.b    gng_TopEdge,3
    dc.w    42
    dc.b    gng_Width,1
    dc.w    24
    dc.b    gng_GadgetText,0
    dc.l    Offset.Label
    dc.b    gng_Flags,0
    dc.l    PLACETEXT_LEFT
    dc.b    gng_UserData,0
    dc.l    OffsetEntered
    dc.b    -1,INTEGER_KIND
    dc.l    Offset.Tags
    EITEM   MainWin.GadCnt

LoadBut.Tags=0
OpenASCII.Tags=0
OpenHexa.Tags=0

Offset.Tags
    dc.l    GTIN_MaxChars,3
    dc.l    TAG_DONE

MainWin.Gads  dcb.l MainWin.GadCnt,0

Ascii.Struct
    dc.l    Hexa.Struct
    dc.l    0
    dc.l    0
    dc.l    0
    dc.l    Ascii.Tags
    dc.l    0           ; PreOpen
    dc.l    Ascii.PostOpen
    dc.l    0           ; PreClose
    dc.l    0           ; PostClose
    dc.l    Ascii.Close
    dc.l    Ascii.MouseBut
    dc.l    Ascii.Render
    dc.b    0,0

Ascii.Tags
    dc.l    WA_Left,0
    dc.l    WA_Top,10
    dc.l    WA_InnerWidth,136
    dc.l    WA_InnerHeight,72
    dc.l    WA_IDCMP,IDCMP
            _REFRESHWINDOW!IDCMP
            _MOUSEBUTTONS!IDCMP
            _CLOSEWINDOW
    dc.l    WA_Flags,WFLG
            _DRAGBAR!WFLG 
            _DEPTHGADGET!WFLG 
            _CLOSEGADGET!WFLG
            _ACTIVATE
    dc.l    WA_Title,Ascii.Title
    dc.l    WA_AutoAdjust,-1
    dc.l    TAG_DONE

Hexa.Struct
    dc.l    0
    dc.l    0
    dc.l    0
    dc.l    0
    dc.l    Hexa.Tags
    dc.l    0           ; PreOpen
    dc.l    Hexa.PostOpen
    dc.l    0           ; PreClose
    dc.l    0           ; PostClose
    dc.l    Hexa.Close
    dc.l    Hexa.MouseBut
    dc.l    Hexa.Render
    dc.b    0,0

Hexa.Tags
    dc.l    WA_Left,0
    dc.l    WA_Top,100
    dc.l    WA_InnerWidth,382
    dc.l    WA_InnerHeight,72
    dc.l    WA_IDCMP,IDCMP 
            _REFRESHWINDOW!IDCMP 
            _MOUSEBUTTONS!IDCMP
            _CLOSEWINDOW
    dc.l    WA_Flags,WFLG
            _DRAGBAR!WFLG 
            _DEPTHGADGET!WFLG 
            _CLOSEGADGET!WFLG
            _ACTIVATE
    dc.l    WA_Title,Hexa.Title
    dc.l    WA_AutoAdjust,-1
    dc.l    TAG_DONE

NewGadget.Struct
    dc.w    0,0,0,0
    dc.l    0,Topaz.TextAttr
    dc.w    0
    dc.l    0

Screen.VisualInfo
    dc.l    0,0

Topaz.TextAttr
    dc.l    Topaz.Name
    dc.w    8,0

WB.Startup      dc.l        0
Intuition.Base  dc.l        0
GadTools.Base   dc.l        0
DOS.Base        dc.l        0
Graphics.Base   dc.l        0
Topaz.TextFont  dc.l        0
Locked.Screen   dc.l        0
QuitStack       dc.l        0
IM.Class        dc.l        0
IM.IAddress     dc.l        0
IM.Code         dc.w        0

Intuition.Name  dc.b        'intuition.library',0
GadTools.Name   dc.b        'gadtools.library',0
DOS.Name        dc.b        'dos.library',0
Graphics.Name   dc.b        'graphics.library',0
Topaz.Name      dc.b        'topaz.font',0
MainWin.Title   dc.b        'Simple viewer',0
Ascii.Title     dc.b        'ASCII view',0
Hexa.Title      dc.b         'Hexadecimal view',0
Load.Label      dc.b        'Load file',0
ASCII.Label     dc.b        'ASCII',0
Hexa.Label      dc.b        'Hexa.',0
Offset.Label    dc.b        'Offset',0
File.Name       dc.b        'RAM:File',0

    section Buffers,BSS
File.BufSize    EQU     128
File.Buffer     ds.b    File.BufSize


[Retour en haut] / [Retour aux articles] [Article précédent] / [Article suivant]