1 /**************************************************************
2 **** Utility.c: some useful functions, by T.Pierron ****
3 **** Free software under GNU license, started on 17/2/2000 ****
4 **************************************************************/
7 #include <intuition/intuitionbase.h>
8 #include <workbench/startup.h>
9 #include <utility/tagitem.h>
11 #include <exec/memory.h>
18 #include "ProtoTypes.h"
20 #define CATCOMP_NUMBERS
23 extern struct IntuitionBase
*IntuitionBase
;
24 extern ULONG err_time
;
25 static UBYTE SPrintfBuf
[80], *savea3
;
27 /** SPrintf like routine **/
31 #include <aros/asmcall.h>
33 AROS_UFH2(void, PutChProc
,
34 AROS_UFHA(UBYTE
, data
, D0
),
35 AROS_UFHA(STRPTR
*, p
, A3
))
39 #elif defined( __GNUC__ )
41 void PutChProc( void ) /* Register based-argument passing with gcc */
43 register UBYTE data
__asm("d0");
45 #else /* Same proc with SAS/C */
47 void __asm
PutChProc(register __d0 UBYTE data
, register __a3 STRPTR out
)
50 /* Can't use a3 ; compiler will restore register content on exit */
51 if( savea3
< SPrintfBuf
+ sizeof(SPrintfBuf
) - 1 )
60 /** This is a very simplified routine, but takes only a few hundreed of bytes **/
61 STRPTR
my_SPrintf(STRPTR fmt
, APTR data
)
64 RawDoFmt(fmt
, data
, (void *)PutChProc
, 0);
68 STRPTR InfoTmpl
= "%4ld, %5ld ";
70 /** Write column/line in top of window **/
71 void draw_info(Project p
)
73 extern WORD fginfo
, bginfo
;
74 struct { ULONG x
; ULONG y
; } coord
;
77 coord
.x
= p
->nbrc
+1; coord
.y
= p
->nbl
+1; savea3
= SPrintfBuf
;
78 RawDoFmt(InfoTmpl
, &coord
, (void *)PutChProc
, 0);
80 RP
= (prefs
.use_pub
? &Scr
->RastPort
: &RPT
);
82 SetABPenDrMd(RP
,fginfo
,bginfo
,JAM2
);
83 Move(RP
,gui
.xinfo
,gui
.yinfo
);
84 Text(RP
, SPrintfBuf
, savea3
-SPrintfBuf
-1);
87 /** Convert argv table into a WBArg one **/
88 void ParseArgs(StartUpArgs
*res
, int nb
, char **argv
)
93 /* Program has been started from Workbench */
94 res
->sa_NbArgs
= ((struct WBStartup
*)argv
)->sm_NumArgs
-1;
95 res
->sa_ArgLst
= (APTR
)(((struct WBStartup
*)argv
)->sm_ArgList
+1);
99 if((new = (void *) AllocVec(sizeof(*new)*(--nb
), MEMF_PUBLIC
| MEMF_CLEAR
)))
101 BPTR cwd
= (BPTR
) CurrentDir( NULL
); /* No need to UnLock so */
102 res
->sa_ArgLst
= (APTR
) new;
105 for(argv
++; nb
; new->wa_Name
= *argv
++, new->wa_Lock
= cwd
, new++, nb
--);
111 /** Get the filename inside #include directive **/
112 STRPTR
GetIncludeFile(Project prj
, LINE
* ln
)
114 STRPTR p
= ln
->stream
;
117 while(i
&& TypeChar
[ *p
] == SPACE
) p
++, i
--;
118 if( i
> 0 && *p
== '#' )
120 for(p
++, i
--; i
&& TypeChar
[*p
] == SPACE
; p
++, i
--);
121 if( i
> 7 && 0 == strncmp(p
, "include", 7) )
123 for(p
+=7, i
-=7; i
&& TypeChar
[*p
] == SPACE
; p
++, i
--);
126 extern UBYTE BufTxt
[];
127 STRPTR dest
= BufTxt
;
129 if(*p
== '<') strcpy(BufTxt
, "INCLUDE:"), dest
+=8, end
= '>';
130 else if(prj
->path
== NULL
) BufTxt
[0] = 0;
132 CopyMem(prj
->path
, BufTxt
, prj
->name
-prj
->path
);
133 dest
+= prj
->name
-prj
->path
;
135 for(p
++, i
--; i
&& *p
!= end
; *dest
++ = *p
++, i
--);
137 if(RETURN_OK
== get_full_path(BufTxt
, &dest
))
145 /* Generic list used ONLY as pointer */
148 struct _list
*next
, *prev
;
151 /*** Insert node Src after the node It ***/
152 void InsertAfter( list It
,list Src
)
158 Src
->next
= L
; Src
->prev
= Lp
;
159 if( L
) L
->prev
= Src
;
160 if( Lp
) Lp
->next
= Src
;
162 Src
->next
= Src
->prev
= NULL
;
165 /*** Remove a node from a list ***/
166 void Destroy( list
*First
, list p
)
168 if(p
->next
) p
->next
->prev
= p
->prev
;
169 if(p
->prev
) p
->prev
->next
= p
->next
;
170 else *First
= p
->next
;
173 /*** Catenate two path part ***/
174 STRPTR
CatPath(STRPTR dir
, STRPTR file
)
178 if( ( dst
= (STRPTR
) AllocVec(len
= strlen(dir
) + strlen(file
) + 2, MEMF_PUBLIC
) ) )
179 strcpy(dst
, dir
), AddPart(dst
, file
, len
);
183 /*** MemMove: copy overlapping chunk of mem ***/
184 void MemMove(UBYTE
*Src
, UWORD Offset
, LONG sz
)
186 register UBYTE
*src
, *dst
;
187 for(src
=Src
+sz
-1, dst
=src
+Offset
; sz
>0; sz
--, *dst
-- = *src
--);
190 static UBYTE TabStop
[256], tab
=255;
192 /*** Pre-computes tabstop ***/
193 void init_tabstop(UBYTE ts
)
197 for(i
=0, tab
=ts
; i
<sizeof(TabStop
); i
++)
200 if(tab
==1) tab
=ts
; else tab
--;
206 /*** Returns increment up to the next tabstop ***/
207 UBYTE
tabstop(ULONG nb
)
209 /* Almost all tabulations are situated before the 256th character */
210 if(nb
<=sizeof(TabStop
)) return TabStop
[nb
];
211 else return (UBYTE
)(tab
- (nb
% tab
));
214 /*** Display an error message in the window's title ***/
215 void ThrowError(struct Window
*W
, STRPTR Msg
)
218 if(Msg
[0] != 127) DisplayBeep(W
->WScreen
); else Msg
++;
220 /* If window is backdrop'ed, change screen's title instead of window */
221 if(W
->Flags
& WFLG_BACKDROP
) SetWindowTitles(W
,(UBYTE
*)-1,Msg
);
222 else SetWindowTitles(W
,Msg
,(UBYTE
*)-1);
225 /* To be sure that mesage will be disappear one day */
226 ModifyIDCMP(W
,W
->IDCMPFlags
| IDCMP_INTUITICKS
);
230 /*** Show messages associated with IoErr() number ***/
231 void ThrowDOSError(struct Window
*W
, STRPTR Prefix
)
233 static UBYTE Message
[100];
235 /* Get standard DOS error message */
236 Fault(IoErr(), Prefix
, Message
, sizeof(Message
));
238 ThrowError(W
, Message
);
241 /*** Set title of window/screen properly ***/
242 void SetTitle(struct Window
*W
, STRPTR Msg
)
244 /* If there is a pending msg, change hidden title */
245 if( W
->IDCMPFlags
& IDCMP_INTUITICKS
)
246 ModifyIDCMP(W
,W
->IDCMPFlags
& ~IDCMP_INTUITICKS
);
248 /* Modify visible title */
249 if(W
->Flags
& WFLG_BACKDROP
) SetWindowTitles(W
,(UBYTE
*)-1,Msg
);
250 else SetWindowTitles(W
,Msg
,(UBYTE
*)-1);
254 /*** Reset the old title ***/
255 void StopError(struct Window
*W
)
257 if(W
->Flags
& WFLG_BACKDROP
) SetWindowTitles(W
,(UBYTE
*)-1,W
->UserData
);
258 else SetWindowTitles(W
,W
->UserData
,(UBYTE
*)-1);
260 /* INTUITICKS aren't required anymore */
261 ModifyIDCMP(W
,W
->IDCMPFlags
& ~IDCMP_INTUITICKS
);
264 /** Getting standard busy pointer **/
266 struct TagItem busy_pointer_tags
[] =
268 {WA_BusyPointer
,TRUE
},
272 /*** Shutdown window IDCMP port ***/
273 void BusyWindow(struct Window
*W
)
277 /* Store IDCMP flags and shutdown port */
278 IDCMPFlags
= W
->IDCMPFlags
;
280 /* Change window's pointer (OS 3.0+ only) */
281 if(IntuitionBase
->LibNode
.lib_Version
>= 39)
282 SetWindowPointerA(W
,busy_pointer_tags
);
286 /*** Reset IDCMP port ***/
287 void WakeUp(struct Window
*W
)
290 ModifyIDCMP(W
,IDCMPFlags
),
294 /* Information window about current project */
295 struct EasyStruct request
;
297 /*** Don't know where to put this one... ***/
298 void show_info(Project p
)
300 extern UBYTE Version
[], WinTitle
[], szEOL
[];
305 request
.es_StructSize
= sizeof(struct EasyStruct
);
306 CopyMem(MsgAbout
, &request
.es_Title
, 3*sizeof(STRPTR
));
307 bytes
= size_count(p
->the_line
, szEOL
[ p
->eol
]);
308 split_path((AskArgs
*)&p
->path
, NULL
, &file
);
310 EasyRequest(Wnd
,&request
,0,(ULONG
)WinTitle
,(ULONG
)(Version
+sizeof(SVER
)-sizeof(TARGET
)),(ULONG
)file
,
311 p
->max_lines
,(ULONG
)MsgAbout
[ p
->max_lines
>1 ? 6:5 ],bytes
,(ULONG
)MsgAbout
[ bytes
>1 ? 4:3 ]);
315 /*** Avert user that its file has been modified ***/
316 char warn_modif(Project p
)
319 if( p
->state
& MODIFIED
)
321 request
.es_StructSize
= sizeof(struct EasyStruct
);
322 request
.es_Title
= MsgAbout
[0];
323 request
.es_TextFormat
= ErrMsg(ERR_FILEMODIFIED
);
324 request
.es_GadgetFormat
= ErrMsg(ERR_SLC
);
325 split_path((AskArgs
*)&p
->path
, NULL
, &file
);
326 switch( EasyRequest(Wnd
,&request
,0,(ULONG
)file
) )
329 case 1: return save_project(p
, FALSE
, FALSE
);
332 /* User want to close this file */
336 /*** Avert user that he is going to overwrite a file ***/
337 char warn_overwrite( STRPTR path
)
340 if(NULL
!= (lock
= (APTR
) Lock( path
, SHARED_LOCK
)))
342 UnLock( (BPTR
) lock
);
343 /* Fuck'n shit, the file exists */
344 request
.es_StructSize
= sizeof(struct EasyStruct
);
345 request
.es_Title
= MsgAbout
[0];
346 request
.es_TextFormat
= ErrMsg(ERR_FILEEXISTS
);
347 request
.es_GadgetFormat
= ErrMsg(ERR_OC
);
349 return (char) EasyRequest(Wnd
,&request
,0,(IPTR
)NULL
);
354 /*** Simple requester to ask user for a number ***/
355 int get_number( Project p
, CONST_STRPTR title
, LONG
* result
)
358 static UBYTE LineNum
[10];
359 static struct StringInfo SI
= {LineNum
,NULL
,0,sizeof(LineNum
),0,0,0,0,0,0,NULL
,0,NULL
};
360 static struct Gadget StrGad
= {
361 NULL
,0,0,0,0,GFLG_GADGHCOMP
,GACT_IMMEDIATE
| GACT_RELVERIFY
| GACT_LONGINT
| GACT_STRINGCENTER
,
362 GTYP_STRGADGET
,NULL
,NULL
,NULL
,0,(APTR
) &SI
,0,NULL
365 /* Open our window */
366 if((win
= (void *) OpenWindowTags( NULL
,
368 WA_InnerHeight
, prefs
.scrfont
->tf_YSize
+2,
369 WA_Left
, Wnd
->LeftEdge
+ (Wnd
->Width
- 160) / 2,
370 WA_Top
, Wnd
->TopEdge
+ (Wnd
->Height
- 30) / 2,
371 WA_Title
, (ULONG
) title
,
372 WA_IDCMP
, IDCMP_CLOSEWINDOW
| IDCMP_GADGETUP
,
373 WA_Flags
, WFLG_CLOSEGADGET
| WFLG_ACTIVATE
| WFLG_RMBTRAP
| WFLG_DRAGBAR
,
374 WA_PubScreen
, (ULONG
) Scr
,
377 extern struct IntuiMessage msgbuf
,*msg
;
380 /* Attach the simple OS1.3 compliant string gadget */
382 StrGad
.Width
= 160 - win
->BorderRight
- (
383 StrGad
.LeftEdge
= win
->BorderLeft
);
384 StrGad
.TopEdge
= win
->BorderTop
+1;
385 StrGad
.Height
= prefs
.scrfont
->tf_YSize
;
386 AddGList(win
, &StrGad
, 0, 1, NULL
);
387 ActivateGadget(&StrGad
, win
, NULL
);
389 /* Quickly collects events */
392 WaitPort( win
->UserPort
);
394 while((msg
= (struct IntuiMessage
*)GetMsg(win
->UserPort
)))
396 CopyMemQuick(msg
, &msgbuf
, sizeof(msgbuf
));
397 ReplyMsg((struct Message
*)msg
);
399 switch( msgbuf
.Class
)
402 case IDCMP_CLOSEWINDOW
: goto the_end
;
406 /* Cleanup everything */
407 the_end
: WakeUp(Wnd
);
409 *result
= SI
.LongInt
;
411 if( LineNum
[0] != 0 ) return 1;
413 } else ThrowError(Wnd
, ErrMsg(ERR_NOMEM
));