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
[80], *savea3
;
29 /** SPrintf like routine **/
33 #include <aros/asmcall.h>
35 AROS_UFH2(void, PutChProc
,
36 AROS_UFHA(UBYTE
, data
, D0
),
37 AROS_UFHA(STRPTR
*, p
, A3
))
41 #elif defined( __GNUC__ )
43 void PutChProc( void ) /* Register based-argument passing with gcc */
45 register UBYTE data
__asm("d0");
47 #else /* Same proc with SAS/C */
49 void __asm
PutChProc(register __d0 UBYTE data
, register __a3 STRPTR out
)
52 /* Can't use a3 ; compiler will restore register content on exit */
53 if( savea3
< SPrintfBuf
+ sizeof(SPrintfBuf
) - 1 )
62 /** This is a very simplified routine, but takes only a few hundred bytes **/
63 STRPTR
my_SPrintf(STRPTR fmt
, APTR data
)
66 RawDoFmt(fmt
, data
, (void *)PutChProc
, 0);
70 /** Write column/line in top of window **/
71 void draw_info(Project p
)
76 CONST_STRPTR InfoTmpl
= "%s%s (%ld, %ld)";
78 /** Update window title **/
79 void UpdateTitle(struct Window
*W
, Project p
)
81 struct { TEXT
*name
; TEXT
*modified
; ULONG x
; ULONG y
; } info
;
83 info
.name
= p
->path
? p
->path
: p
->name
;
84 info
.modified
= (p
->state
& MODIFIED
) ? STR_MODIF
: "";
85 info
.x
= p
->nbrc
+1; info
.y
= p
->nbl
+1; savea3
= SPrintfBuf
;
86 RawDoFmt(InfoTmpl
, &info
, (void *)PutChProc
, 0);
88 SetTitle(W
, SPrintfBuf
);
91 /** Convert argv table into a WBArg one **/
92 void ParseArgs(StartUpArgs
*res
, int nb
, char **argv
)
97 /* Program has been started from Workbench */
98 res
->sa_NbArgs
= ((struct WBStartup
*)argv
)->sm_NumArgs
-1;
99 res
->sa_ArgLst
= (APTR
)(((struct WBStartup
*)argv
)->sm_ArgList
+1);
100 } else if( nb
> 1 ) {
103 if((new = (void *) AllocVec(sizeof(*new)*(--nb
), MEMF_PUBLIC
| MEMF_CLEAR
)))
105 BPTR cwd
= (BPTR
) CurrentDir( NULL
); /* No need to UnLock so */
106 res
->sa_ArgLst
= (APTR
) new;
109 for(argv
++; nb
; new->wa_Name
= *argv
++, new->wa_Lock
= cwd
, new++, nb
--);
115 /** Get the filename inside #include directive **/
116 STRPTR
GetIncludeFile(Project prj
, LINE
* ln
)
118 STRPTR p
= ln
->stream
;
121 while(i
&& TypeChar
[ *p
] == SPACE
) p
++, i
--;
122 if( i
> 0 && *p
== '#' )
124 for(p
++, i
--; i
&& TypeChar
[*p
] == SPACE
; p
++, i
--);
125 if( i
> 7 && 0 == strncmp(p
, "include", 7) )
127 for(p
+=7, i
-=7; i
&& TypeChar
[*p
] == SPACE
; p
++, i
--);
130 extern UBYTE BufTxt
[];
131 STRPTR dest
= BufTxt
;
133 if(*p
== '<') strcpy(BufTxt
, "INCLUDE:"), dest
+=8, end
= '>';
134 else if(prj
->path
== NULL
) BufTxt
[0] = 0;
136 CopyMem(prj
->path
, BufTxt
, prj
->name
-prj
->path
);
137 dest
+= prj
->name
-prj
->path
;
139 for(p
++, i
--; i
&& *p
!= end
; *dest
++ = *p
++, i
--);
141 if(RETURN_OK
== get_full_path(BufTxt
, &dest
))
149 /* Generic list used ONLY as pointer */
152 struct _list
*next
, *prev
;
155 /*** Insert node Src after the node It ***/
156 void InsertAfter( list It
,list Src
)
162 Src
->next
= L
; Src
->prev
= Lp
;
163 if( L
) L
->prev
= Src
;
164 if( Lp
) Lp
->next
= Src
;
166 Src
->next
= Src
->prev
= NULL
;
169 /*** Remove a node from a list ***/
170 void Destroy( list
*First
, list p
)
172 if(p
->next
) p
->next
->prev
= p
->prev
;
173 if(p
->prev
) p
->prev
->next
= p
->next
;
174 else *First
= p
->next
;
177 /*** Catenate two path part ***/
178 STRPTR
CatPath(STRPTR dir
, STRPTR file
)
182 if( ( dst
= (STRPTR
) AllocVec(len
= strlen(dir
) + strlen(file
) + 2, MEMF_PUBLIC
) ) )
183 strcpy(dst
, dir
), AddPart(dst
, file
, len
);
187 /*** MemMove: copy overlapping chunk of mem ***/
188 void MemMove(UBYTE
*Src
, UWORD Offset
, LONG sz
)
190 register UBYTE
*src
, *dst
;
191 for(src
=Src
+sz
-1, dst
=src
+Offset
; sz
>0; sz
--, *dst
-- = *src
--);
194 static UBYTE TabStop
[256], tab
=255;
196 /*** Pre-computes tabstop ***/
197 void init_tabstop(UBYTE ts
)
201 for(i
=0, tab
=ts
; i
<sizeof(TabStop
); i
++)
204 if(tab
==1) tab
=ts
; else tab
--;
210 /*** Returns increment up to the next tabstop ***/
211 UBYTE
tabstop(ULONG nb
)
213 /* Almost all tabulations are situated before the 256th character */
214 if(nb
<=sizeof(TabStop
)) return TabStop
[nb
];
215 else return (UBYTE
)(tab
- (nb
% tab
));
218 /*** Display an error message in the window's title ***/
219 void ThrowError(struct Window
*W
, STRPTR Msg
)
222 if(Msg
[0] != 127) DisplayBeep(W
->WScreen
); else Msg
++;
224 /* If window is backdrop'ed, change screen's title instead of window */
225 if(W
->Flags
& WFLG_BACKDROP
) SetWindowTitles(W
,(UBYTE
*)-1,Msg
);
226 else SetWindowTitles(W
,Msg
,(UBYTE
*)-1);
229 /* To be sure that message will disappear one day */
230 ModifyIDCMP(W
,W
->IDCMPFlags
| IDCMP_INTUITICKS
);
234 /*** Show messages associated with IoErr() number ***/
235 void ThrowDOSError(struct Window
*W
, STRPTR Prefix
)
237 static UBYTE Message
[100];
239 /* Get standard DOS error message */
240 Fault(IoErr(), Prefix
, Message
, sizeof(Message
));
242 ThrowError(W
, Message
);
245 /*** Set title of window/screen properly ***/
246 void SetTitle(struct Window
*W
, STRPTR Msg
)
248 /* If there is a pending msg, change hidden title */
249 if( W
->IDCMPFlags
& IDCMP_INTUITICKS
)
250 ModifyIDCMP(W
,W
->IDCMPFlags
& ~IDCMP_INTUITICKS
);
252 /* Modify visible title */
253 if(W
->Flags
& WFLG_BACKDROP
) SetWindowTitles(W
,(UBYTE
*)-1,Msg
);
254 else SetWindowTitles(W
,Msg
,(UBYTE
*)-1);
258 /*** Reset the old title ***/
259 void StopError(struct Window
*W
)
261 if(W
->Flags
& WFLG_BACKDROP
) SetWindowTitles(W
,(UBYTE
*)-1,W
->UserData
);
262 else SetWindowTitles(W
,W
->UserData
,(UBYTE
*)-1);
264 /* INTUITICKS aren't required anymore */
265 ModifyIDCMP(W
,W
->IDCMPFlags
& ~IDCMP_INTUITICKS
);
268 /** Getting standard busy pointer **/
270 struct TagItem busy_pointer_tags
[] =
272 {WA_BusyPointer
,TRUE
},
276 /*** Shutdown window IDCMP port ***/
277 void BusyWindow(struct Window
*W
)
281 /* Store IDCMP flags and shutdown port */
282 IDCMPFlags
= W
->IDCMPFlags
;
284 /* Change window's pointer (OS 3.0+ only) */
285 if(IntuitionBase
->LibNode
.lib_Version
>= 39)
286 SetWindowPointerA(W
,busy_pointer_tags
);
290 /*** Reset IDCMP port ***/
291 void WakeUp(struct Window
*W
)
294 ModifyIDCMP(W
,IDCMPFlags
),
298 /* Information window about current project */
299 struct EasyStruct request
;
301 /*** Show information window ***/
302 void show_info(Project p
)
304 extern UBYTE WinTitle
[], szEOL
[];
309 request
.es_StructSize
= sizeof(struct EasyStruct
);
310 CopyMem(MsgAbout
, &request
.es_Title
, 3*sizeof(STRPTR
));
311 bytes
= size_count(p
->the_line
, szEOL
[ p
->eol
]);
312 split_path((AskArgs
*)&p
->path
, NULL
, &file
);
314 EasyRequest(Wnd
,&request
,NULL
,(ULONG
)WinTitle
,file
,
315 p
->max_lines
,MsgAbout
[ p
->max_lines
!=1 ? 6:5 ],
316 bytes
,MsgAbout
[ bytes
!=1 ? 4:3 ]);
320 /*** Warn user that file has been modified ***/
321 char warn_modif(Project p
)
324 if( p
->state
& MODIFIED
)
326 request
.es_StructSize
= sizeof(struct EasyStruct
);
327 request
.es_Title
= MsgAbout
[0];
328 request
.es_TextFormat
= ErrMsg(ERR_FILEMODIFIED
);
329 request
.es_GadgetFormat
= ErrMsg(ERR_SLC
);
330 split_path((AskArgs
*)&p
->path
, NULL
, &file
);
331 switch( EasyRequest(Wnd
,&request
,0,(ULONG
)file
) )
334 case 1: return save_project(p
, FALSE
, FALSE
);
337 /* User want to close this file */
341 /*** Warn user that he is going to overwrite a file ***/
342 char warn_overwrite( STRPTR path
)
345 if(NULL
!= (lock
= (APTR
) Lock( path
, SHARED_LOCK
)))
347 UnLock( (BPTR
) lock
);
348 /* Fuck'n shit, the file exists */
349 request
.es_StructSize
= sizeof(struct EasyStruct
);
350 request
.es_Title
= MsgAbout
[0];
351 request
.es_TextFormat
= ErrMsg(ERR_FILEEXISTS
);
352 request
.es_GadgetFormat
= ErrMsg(ERR_OC
);
354 return (char) EasyRequest(Wnd
,&request
,0,(IPTR
)NULL
);
359 /*** Simple requester to ask user for a number ***/
360 int get_number( Project p
, CONST_STRPTR title
, LONG
* result
)
363 static UBYTE LineNum
[10];
364 static struct StringInfo SI
= {LineNum
,NULL
,0,sizeof(LineNum
),0,0,0,0,0,0,NULL
,0,NULL
};
365 static struct Gadget StrGad
= {
366 NULL
,0,0,0,0,GFLG_GADGHCOMP
,GACT_IMMEDIATE
| GACT_RELVERIFY
| GACT_LONGINT
| GACT_STRINGCENTER
,
367 GTYP_STRGADGET
,NULL
,NULL
,NULL
,0,(APTR
) &SI
,0,NULL
370 /* Open our window */
371 if((win
= (void *) OpenWindowTags( NULL
,
373 WA_InnerHeight
, prefs
.scrfont
->tf_YSize
+2,
374 WA_Left
, Wnd
->LeftEdge
+ (Wnd
->Width
- 160) / 2,
375 WA_Top
, Wnd
->TopEdge
+ (Wnd
->Height
- 30) / 2,
376 WA_Title
, (ULONG
) title
,
377 WA_IDCMP
, IDCMP_CLOSEWINDOW
| IDCMP_GADGETUP
,
378 WA_Flags
, WFLG_CLOSEGADGET
| WFLG_ACTIVATE
| WFLG_RMBTRAP
| WFLG_DRAGBAR
,
379 WA_PubScreen
, (ULONG
) Scr
,
382 extern struct IntuiMessage msgbuf
,*msg
;
385 /* Attach the simple OS1.3 compliant string gadget */
387 StrGad
.Width
= 160 - win
->BorderRight
- (
388 StrGad
.LeftEdge
= win
->BorderLeft
);
389 StrGad
.TopEdge
= win
->BorderTop
+1;
390 StrGad
.Height
= prefs
.scrfont
->tf_YSize
;
391 AddGList(win
, &StrGad
, 0, 1, NULL
);
392 ActivateGadget(&StrGad
, win
, NULL
);
394 /* Quickly collects events */
397 WaitPort( win
->UserPort
);
399 while((msg
= (struct IntuiMessage
*)GetMsg(win
->UserPort
)))
401 CopyMemQuick(msg
, &msgbuf
, sizeof(msgbuf
));
402 ReplyMsg((struct Message
*)msg
);
404 switch( msgbuf
.Class
)
407 case IDCMP_CLOSEWINDOW
: goto the_end
;
411 /* Cleanup everything */
412 the_end
: WakeUp(Wnd
);
414 *result
= SI
.LongInt
;
416 if( LineNum
[0] != 0 ) return 1;
418 } else ThrowError(Wnd
, ErrMsg(ERR_NOMEM
));