Suivez-nous sur X
|
|
|
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,
ALL
|
|
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
|
|
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
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
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
|
|