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 void SetTitle(struct Window
*, STRPTR
);
25 extern struct IntuitionBase
*IntuitionBase
;
26 extern ULONG err_time
;
27 static UBYTE SPrintfBuf
[256], *savea3
;
29 /* Different End Of Line markers */
30 const UBYTE chEOL
[] = {'\n', '\r', '\r', '\n'};
31 const UBYTE szEOL
[] = {1, 1, 2};
33 /** SPrintf like routine **/
37 #include <aros/asmcall.h>
39 AROS_UFH2(void, PutChProc
,
40 AROS_UFHA(UBYTE
, data
, D0
),
41 AROS_UFHA(STRPTR
*, p
, A3
))
45 #elif defined( __GNUC__ )
47 void PutChProc( void ) /* Register based-argument passing with gcc */
49 register UBYTE data
__asm("d0");
51 #else /* Same proc with SAS/C */
53 void __asm
PutChProc(register __d0 UBYTE data
, register __a3 STRPTR out
)
56 /* Can't use a3 ; compiler will restore register content on exit */
57 if( savea3
< SPrintfBuf
+ sizeof(SPrintfBuf
) - 1 )
66 /** This is a very simplified routine, but takes only a few hundred bytes **/
67 STRPTR
my_SPrintf(STRPTR fmt
, RAWARG data
)
70 RawDoFmt(fmt
, (RAWARG
)data
, (void *)PutChProc
, 0);
74 /** Write column/line in top of window **/
75 void draw_info(Project p
)
80 CONST_STRPTR InfoTmpl
= "%s%s (%iu, %iu)";
82 /** Update window title **/
83 void UpdateTitle(struct Window
*W
, Project p
)
85 struct { TEXT
*name
; TEXT
*modified
; STACKED ULONG x
; STACKED ULONG y
; } __packed info
;
87 info
.name
= p
->path
? p
->path
: p
->name
;
88 info
.modified
= (p
->state
& MODIFIED
) ? STR_MODIF
: "";
89 info
.x
= p
->nbrc
+1; info
.y
= p
->nbl
+1; savea3
= SPrintfBuf
;
90 RawDoFmt(InfoTmpl
, (RAWARG
)&info
, (void *)PutChProc
, 0);
92 SetTitle(W
, SPrintfBuf
);
95 /** Convert argv table into a WBArg one **/
96 void ParseArgs(StartUpArgs
*res
, int nb
, char **argv
)
101 /* Program has been started from Workbench */
102 res
->sa_NbArgs
= ((struct WBStartup
*)argv
)->sm_NumArgs
-1;
103 res
->sa_ArgLst
= (APTR
)(((struct WBStartup
*)argv
)->sm_ArgList
+1);
104 } else if( nb
> 1 ) {
107 if((new = (void *) AllocVec(sizeof(*new)*(--nb
), MEMF_PUBLIC
| MEMF_CLEAR
)))
109 BPTR cwd
= (BPTR
) CurrentDir( BNULL
); /* No need to UnLock so */
110 res
->sa_ArgLst
= (APTR
) new;
113 for(argv
++; nb
; new->wa_Name
= *argv
++, new->wa_Lock
= cwd
, new++, nb
--);
119 /** Get the filename inside #include directive **/
120 STRPTR
GetIncludeFile(Project prj
, LINE
* ln
)
122 STRPTR p
= ln
->stream
;
125 while(i
&& TypeChar
[ *p
] == SPACE
) p
++, i
--;
126 if( i
> 0 && *p
== '#' )
128 for(p
++, i
--; i
&& TypeChar
[*p
] == SPACE
; p
++, i
--);
129 if( i
> 7 && 0 == strncmp(p
, "include", 7) )
131 for(p
+=7, i
-=7; i
&& TypeChar
[*p
] == SPACE
; p
++, i
--);
134 extern UBYTE BufTxt
[];
135 STRPTR dest
= BufTxt
;
137 if(*p
== '<') strcpy(BufTxt
, "INCLUDE:"), dest
+=8, end
= '>';
138 else if(prj
->path
== NULL
) BufTxt
[0] = 0;
140 CopyMem(prj
->path
, BufTxt
, prj
->name
-prj
->path
);
141 dest
+= prj
->name
-prj
->path
;
143 for(p
++, i
--; i
&& *p
!= end
; *dest
++ = *p
++, i
--);
145 if(RETURN_OK
== get_full_path(BufTxt
, &dest
))
153 /* Generic list used ONLY as pointer */
156 struct _list
*next
, *prev
;
159 /*** Insert node Src after the node It ***/
160 void InsertAfter( list It
,list Src
)
166 Src
->next
= L
; Src
->prev
= Lp
;
167 if( L
) L
->prev
= Src
;
168 if( Lp
) Lp
->next
= Src
;
170 Src
->next
= Src
->prev
= NULL
;
173 /*** Remove a node from a list ***/
174 void Destroy( list
*First
, list p
)
176 if(p
->next
) p
->next
->prev
= p
->prev
;
177 if(p
->prev
) p
->prev
->next
= p
->next
;
178 else *First
= p
->next
;
181 /*** Catenate two path part ***/
182 STRPTR
CatPath(STRPTR dir
, STRPTR file
)
186 if( ( dst
= (STRPTR
) AllocVec(len
= strlen(dir
) + strlen(file
) + 2, MEMF_PUBLIC
) ) )
187 strcpy(dst
, dir
), AddPart(dst
, file
, len
);
191 /*** MemMove: copy overlapping chunk of mem ***/
192 void MemMove(UBYTE
*Src
, UWORD Offset
, LONG sz
)
194 register UBYTE
*src
, *dst
;
195 for(src
=Src
+sz
-1, dst
=src
+Offset
; sz
>0; sz
--, *dst
-- = *src
--);
198 static UBYTE TabStop
[256], tab
=255;
200 /*** Pre-computes tabstop ***/
201 void init_tabstop(UBYTE ts
)
205 for(i
=0, tab
=ts
; i
<sizeof(TabStop
); i
++)
208 if(tab
==1) tab
=ts
; else tab
--;
214 /*** Returns increment up to the next tabstop ***/
215 UBYTE
tabstop(ULONG nb
)
217 /* Almost all tabulations are situated before the 256th character */
218 if(nb
<=sizeof(TabStop
)) return TabStop
[nb
];
219 else return (UBYTE
)(tab
- (nb
% tab
));
222 /*** Display an error message in the window's title ***/
223 void ThrowError(struct Window
*W
, STRPTR Msg
)
226 if(Msg
[0] != 127) DisplayBeep(W
->WScreen
); else Msg
++;
228 /* If window is backdrop'ed, change screen's title instead of window */
229 if(W
->Flags
& WFLG_BACKDROP
) SetWindowTitles(W
,(UBYTE
*)-1,Msg
);
230 else SetWindowTitles(W
,Msg
,(UBYTE
*)-1);
233 /* To be sure that message will disappear one day */
234 ModifyIDCMP(W
,W
->IDCMPFlags
| IDCMP_INTUITICKS
);
238 /*** Show messages associated with IoErr() number ***/
239 void ThrowDOSError(struct Window
*W
, STRPTR Prefix
)
241 static UBYTE Message
[100];
243 /* Get standard DOS error message */
244 Fault(IoErr(), Prefix
, Message
, sizeof(Message
));
246 ThrowError(W
, Message
);
249 /*** Set title of window/screen properly ***/
250 void SetTitle(struct Window
*W
, STRPTR Msg
)
252 /* If there is a pending msg, change hidden title */
253 if( W
->IDCMPFlags
& IDCMP_INTUITICKS
)
254 ModifyIDCMP(W
,W
->IDCMPFlags
& ~IDCMP_INTUITICKS
);
256 /* Modify visible title */
257 if(W
->Flags
& WFLG_BACKDROP
) SetWindowTitles(W
,(UBYTE
*)-1,Msg
);
258 else SetWindowTitles(W
,Msg
,(UBYTE
*)-1);
262 /*** Reset the old title ***/
263 void StopError(struct Window
*W
)
265 if(W
->Flags
& WFLG_BACKDROP
) SetWindowTitles(W
,(UBYTE
*)-1,W
->UserData
);
266 else SetWindowTitles(W
,W
->UserData
,(UBYTE
*)-1);
268 /* INTUITICKS aren't required anymore */
269 ModifyIDCMP(W
,W
->IDCMPFlags
& ~IDCMP_INTUITICKS
);
272 /** Getting standard busy pointer **/
274 struct TagItem busy_pointer_tags
[] =
276 {WA_BusyPointer
,TRUE
},
280 /*** Shutdown window IDCMP port ***/
281 void BusyWindow(struct Window
*W
)
285 /* Store IDCMP flags and shutdown port */
286 IDCMPFlags
= W
->IDCMPFlags
;
288 /* Change window's pointer (OS 3.0+ only) */
289 if(IntuitionBase
->LibNode
.lib_Version
>= 39)
290 SetWindowPointerA(W
,busy_pointer_tags
);
294 /*** Reset IDCMP port ***/
295 void WakeUp(struct Window
*W
)
298 ModifyIDCMP(W
,IDCMPFlags
),
302 /* Information window about current project */
303 struct EasyStruct request
;
305 /*** Show information window ***/
306 void show_info(Project p
)
308 extern UBYTE WinTitle
[];
313 request
.es_StructSize
= sizeof(struct EasyStruct
);
314 CopyMem(MsgAbout
, &request
.es_Title
, 3*sizeof(STRPTR
));
315 bytes
= size_count(p
->the_line
, szEOL
[ p
->eol
]);
316 split_path((AskArgs
*)&p
->path
, NULL
, &file
);
318 EasyRequest(Wnd
,&request
,NULL
,(IPTR
)WinTitle
,file
,
319 p
->max_lines
,MsgAbout
[ p
->max_lines
!=1 ? 6:5 ],
320 bytes
,MsgAbout
[ bytes
!=1 ? 4:3 ]);
324 /*** Warn user that file has been modified ***/
325 char warn_modif(Project p
)
328 if( p
->state
& MODIFIED
)
330 request
.es_StructSize
= sizeof(struct EasyStruct
);
331 request
.es_Title
= MsgAbout
[0];
332 request
.es_TextFormat
= ErrMsg(ERR_FILEMODIFIED
);
333 request
.es_GadgetFormat
= ErrMsg(ERR_SLC
);
334 split_path((AskArgs
*)&p
->path
, NULL
, &file
);
335 switch( EasyRequest(Wnd
,&request
,0,(IPTR
)file
) )
338 case 1: return save_project(p
, FALSE
, FALSE
);
341 /* User want to close this file */
345 /*** Warn user that he is going to overwrite a file ***/
346 char warn_overwrite( STRPTR path
)
349 if(NULL
!= (lock
= (APTR
) Lock( path
, SHARED_LOCK
)))
351 UnLock( (BPTR
) lock
);
352 /* Fuck'n shit, the file exists */
353 request
.es_StructSize
= sizeof(struct EasyStruct
);
354 request
.es_Title
= MsgAbout
[0];
355 request
.es_TextFormat
= ErrMsg(ERR_FILEEXISTS
);
356 request
.es_GadgetFormat
= ErrMsg(ERR_OC
);
358 return (char) EasyRequest(Wnd
,&request
,0,(IPTR
)NULL
);
363 /*** Simple requester to ask user for a number ***/
364 int get_number( Project p
, CONST_STRPTR title
, LONG
* result
)
367 static UBYTE LineNum
[10];
368 static struct StringInfo SI
= {LineNum
,NULL
,0,sizeof(LineNum
),0,0,0,0,0,0,NULL
,0,NULL
};
369 static struct Gadget StrGad
= {
370 NULL
,0,0,0,0,GFLG_GADGHCOMP
,GACT_IMMEDIATE
| GACT_RELVERIFY
| GACT_LONGINT
| GACT_STRINGCENTER
,
371 GTYP_STRGADGET
,NULL
,NULL
,NULL
,0,(APTR
) &SI
,0,NULL
374 /* Open our window */
375 if((win
= (void *) OpenWindowTags( NULL
,
377 WA_InnerHeight
, prefs
.scrfont
->tf_YSize
+2,
378 WA_Left
, Wnd
->LeftEdge
+ (Wnd
->Width
- 160) / 2,
379 WA_Top
, Wnd
->TopEdge
+ (Wnd
->Height
- 30) / 2,
380 WA_Title
, (IPTR
) title
,
381 WA_IDCMP
, IDCMP_CLOSEWINDOW
| IDCMP_GADGETUP
,
382 WA_Flags
, WFLG_CLOSEGADGET
| WFLG_ACTIVATE
| WFLG_RMBTRAP
| WFLG_DRAGBAR
,
383 WA_PubScreen
, (IPTR
) Scr
,
386 extern struct IntuiMessage msgbuf
,*msg
;
389 /* Attach the simple OS1.3 compliant string gadget */
391 StrGad
.Width
= 160 - win
->BorderRight
- (
392 StrGad
.LeftEdge
= win
->BorderLeft
);
393 StrGad
.TopEdge
= win
->BorderTop
+1;
394 StrGad
.Height
= prefs
.scrfont
->tf_YSize
;
395 AddGList(win
, &StrGad
, 0, 1, NULL
);
396 ActivateGadget(&StrGad
, win
, NULL
);
398 /* Quickly collects events */
401 WaitPort( win
->UserPort
);
403 while((msg
= (struct IntuiMessage
*)GetMsg(win
->UserPort
)))
405 CopyMemQuick(msg
, &msgbuf
, sizeof(msgbuf
));
406 ReplyMsg((struct Message
*)msg
);
408 switch( msgbuf
.Class
)
411 case IDCMP_CLOSEWINDOW
: goto the_end
;
415 /* Cleanup everything */
416 the_end
: WakeUp(Wnd
);
418 *result
= SI
.LongInt
;
420 if( LineNum
[0] != 0 ) return 1;
422 } else ThrowError(Wnd
, ErrMsg(ERR_NOMEM
));