1 /***************************************************
3 ** $VER: Macros.c 1.0 (15.8.2001) **
4 ** Record sequence of keystrokes **
6 ** © T.Pierron, C.Guilaume. Free software **
7 ** under terms of GNU public license. **
9 ***************************************************/
11 #include <intuition/intuition.h>
12 #include <intuition/screens.h>
13 #include <exec/memory.h>
21 #include "ProtoTypes.h"
23 #define CATCOMP_NUMBERS
26 extern STRPTR InfoTmpl
;
29 static STRPTR OldInfo
= NULL
;
31 UBYTE NewTmpl
[40], TmplLen
, TmplWid
;
33 /** Manage a set of macros **/
34 Macro MainMacro
= NULL
, MacCur
= NULL
, LastChunk
;
37 sizeof( *(ActChar
)0L ),
38 sizeof( *(ActMenu
)0L ),
39 sizeof( *(ActShortcut
)0L )
42 /*** Setup some variables ***/
43 void init_macros( void )
46 /* "FIXME: Missing buffer overflow check!" */
47 strcpy(NewTmpl
, ErrMsg(WARN_REC
)));
48 strcat(NewTmpl
, " "); TmplLen
+= 2;
49 strcat(NewTmpl
, InfoTmpl
);
52 /*** Free memory used by a macro ***/
53 void free_macro( Macro m
)
56 for(; m
; next
= m
->next
, FreeVec(m
), m
= next
);
58 void free_macros( void )
60 free_macro(MainMacro
);
64 /*** Start recording keystrokes ***/
65 void start_macro( void )
69 /* Show a special msg in info template to show reccording state */
73 TmplWid
= TextLength(prefs
.backdrop
? &Scr
->RastPort
: &RPT
, NewTmpl
, TmplLen
);
75 MacCur
= LastChunk
= NULL
;
77 ThrowError(Wnd
, ErrMsg(WARN_RECORD
));
82 void stop_macro( void )
86 InfoTmpl
= OldInfo
; OldInfo
= NULL
;
89 /* Do not save something if nothing has been recorded */
91 free_macro( MainMacro
); MainMacro
= MacCur
; MacCur
= NULL
;
92 ThrowError(Wnd
, ErrMsg(WARN_RECORDED
));
94 else UpdateTitle(Wnd
, edit
);
98 /** Alloc a new chunk for recording keystroke **/
99 void *new_action( UWORD size
)
101 if(LastChunk
== NULL
|| LastChunk
->usage
+ size
> SZ_MACRO
)
104 /* Alloc a new chunk, not enough room */
105 if(NULL
== (new = (Macro
) AllocVec(sizeof(*new), MEMF_CLEAR
)))
109 LastChunk
->next
= new;
116 else /* Still some place in current chunk */
118 STRPTR
new = LastChunk
->data
+ LastChunk
->usage
;
119 LastChunk
->usage
+= size
;
124 /** Register actions **/
125 void reg_act_addchar( UBYTE code
)
128 if( ( new = new_action( sizeof(*new) ) ) )
129 new->Type
= MAC_ACT_ADD_CHAR
, new->Char
= code
;
131 void reg_act_com( UBYTE type
, UWORD code
, UWORD qual
)
134 if( ( new = new_action( sizeof(*new) ) ) )
135 new->Type
= type
, new->Code
= code
, new->Qual
= qual
;
138 /** Play current macro **/
139 void play_macro( int nb_times
)
141 extern struct IntuiMessage msgbuf
;
142 WORD selmask
, txtmask
;
145 if(MainMacro
== NULL
) return;
147 /* Disconnect display, just to be clean, not for performance */
148 inv_curs(edit
, FALSE
);
149 RP
->Mask
= 0; RPT
.Mask
= 0;
150 selmask
= gui
.selmask
; gui
.selmask
= 0;
151 txtmask
= gui
.txtmask
; gui
.txtmask
= 0;
156 for(m
= MainMacro
; m
; m
= m
->next
)
159 for(eoc
= (op
= m
->data
) + m
->usage
; op
< eoc
; op
+= SzOp
[*op
])
162 case MAC_ACT_ADD_CHAR
:
163 if( add_char(&edit
->undo
, edit
->edited
, edit
->nbc
, ((ActChar
)op
)->Char
) )
165 REDRAW_CURLINE(edit
);
166 curs_right(edit
, FALSE
);
168 case MAC_ACT_COM_MENU
:
169 msgbuf
.Qualifier
= ((ActMenu
)op
)->Qual
;
170 handle_menu( ((ActMenu
)op
)->Code
); break;
171 case MAC_ACT_SHORTCUT
:
172 msgbuf
.Qualifier
= ((ActShortcut
)op
)->Qual
;
173 msgbuf
.Code
= ((ActShortcut
)op
)->Code
;
174 handle_kbd(edit
); break;
178 /* Now we can show changes */
179 gui
.selmask
= selmask
;
180 gui
.txtmask
= txtmask
;
181 RP
->Mask
= (edit
->ccp
.select
? selmask
: txtmask
);
184 redraw_content(edit
, edit
->show
, gui
.topcurs
, gui
.nbline
);
189 void repeat_macro( Project p
)
193 if( MainMacro
&& get_number(p
, GetMenuText(404), &nb
) )
198 /** Select other slot **/
199 void new_slot( BYTE dir
)
201 Macro
*m
= MacTable
+ CurInd
- 1, *last
= m
;
204 if(dir
< 0) m
--; else m
++;
205 if(m
< MacTable
) m
= MacTable
+ MAX_MAC
;
206 if(m
>= MacTable
+MAX_MAC
) m
= MacTable
;
207 if(last
== m
|| *m
!= NULL
) break;
209 CurInd
= m
- MacTable
+ 1;
211 ThrowError(Wnd
, my_SPrintf(*m
? ErrMsg(WARN_SLOT
) : ErrMsg(WARN_EMPTYSLOT
), (RAWARG
)&CurInd
));