Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / tools / Edit / Utility.c
blob40a63e0c5d22bda77373ef5d3875f0e95d737cb8
1 /**************************************************************
2 **** Utility.c: some useful functions, by T.Pierron ****
3 **** Free software under GNU license, started on 17/2/2000 ****
4 **************************************************************/
6 #define UTILITY_C
7 #include <intuition/intuitionbase.h>
8 #include <workbench/startup.h>
9 #include <utility/tagitem.h>
10 #include <dos/dos.h>
11 #include <exec/memory.h>
12 #include <exec/io.h>
13 #include "ClipLoc.h"
14 #include "Project.h"
15 #include "Gui.h"
16 #include "Utility.h"
17 #include "DiskIO.h"
18 #include "ProtoTypes.h"
20 #define CATCOMP_NUMBERS
21 #include "strings.h"
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 **/
32 #ifdef __AROS__
33 #include <aros/asmcall.h>
35 AROS_UFH2(void, PutChProc,
36 AROS_UFHA(UBYTE, data, D0),
37 AROS_UFHA(STRPTR *, p, A3))
39 AROS_USERFUNC_INIT
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)
51 #endif
52 /* Can't use a3 ; compiler will restore register content on exit */
53 if( savea3 < SPrintfBuf + sizeof(SPrintfBuf) - 1 )
54 *savea3++ = data;
55 else *savea3 = 0;
57 #ifdef __AROS__
58 AROS_USERFUNC_EXIT
59 #endif
62 /** This is a very simplified routine, but takes only a few hundred bytes **/
63 STRPTR my_SPrintf(STRPTR fmt, APTR data)
65 savea3 = SPrintfBuf;
66 RawDoFmt(fmt, data, (void *)PutChProc, 0);
67 return SPrintfBuf;
70 /** Write column/line in top of window **/
71 void draw_info(Project p)
73 UpdateTitle(Wnd, 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)
94 res->sa_Free = 0;
95 res->sa_NbArgs = 0;
96 if( nb == 0 ) {
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 ) {
101 /* From CLI */
102 struct WBArg *new;
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;
107 res->sa_NbArgs = nb;
108 res->sa_Free = 1;
109 for(argv++; nb; new->wa_Name = *argv++, new->wa_Lock = cwd, new++, nb--);
110 CurrentDir( cwd );
115 /** Get the filename inside #include directive **/
116 STRPTR GetIncludeFile(Project prj, LINE * ln)
118 STRPTR p = ln->stream;
119 LONG i = ln->size;
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--);
128 if(i > 2)
130 extern UBYTE BufTxt[];
131 STRPTR dest = BufTxt;
132 UBYTE end = *p;
133 if(*p == '<') strcpy(BufTxt, "INCLUDE:"), dest+=8, end = '>';
134 else if(prj->path == NULL) BufTxt[0] = 0;
135 else {
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--);
140 *dest=0;
141 if(RETURN_OK == get_full_path(BufTxt, &dest))
142 return dest;
146 return NULL;
149 /* Generic list used ONLY as pointer */
150 typedef struct _list
152 struct _list *next, *prev;
153 } *list;
155 /*** Insert node Src after the node It ***/
156 void InsertAfter( list It,list Src )
158 register list L, Lp;
159 if(It)
161 Lp=It; L=Lp->next;
162 Src->next = L; Src->prev = Lp;
163 if( L ) L->prev = Src;
164 if( Lp ) Lp->next= Src;
165 } else
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)
180 STRPTR dst;
181 UWORD len;
182 if( ( dst = (STRPTR) AllocVec(len = strlen(dir) + strlen(file) + 2, MEMF_PUBLIC) ) )
183 strcpy(dst, dir), AddPart(dst, file, len);
184 return dst;
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)
199 if(ts != tab) {
200 int i;
201 for(i=0, tab=ts; i<sizeof(TabStop); i++)
203 TabStop[i] = tab;
204 if(tab==1) tab=ts; else tab--;
206 tab=ts;
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)
221 if( W ) {
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);
228 err_time = 0;
229 /* To be sure that message will disappear one day */
230 ModifyIDCMP(W,W->IDCMPFlags | IDCMP_INTUITICKS);
231 } else puts(Msg);
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);
255 W->UserData = Msg;
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 **/
269 ULONG IDCMPFlags;
270 struct TagItem busy_pointer_tags[] =
272 {WA_BusyPointer,TRUE},
273 {TAG_END,0}
276 /*** Shutdown window IDCMP port ***/
277 void BusyWindow(struct Window *W)
279 if( W )
281 /* Store IDCMP flags and shutdown port */
282 IDCMPFlags = W->IDCMPFlags;
283 ModifyIDCMP(W,0);
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)
293 if( W )
294 ModifyIDCMP(W,IDCMPFlags),
295 ClearPointer(W);
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[];
305 STRPTR file;
306 ULONG bytes;
308 BusyWindow(Wnd);
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 ]);
317 WakeUp(Wnd);
320 /*** Warn user that file has been modified ***/
321 char warn_modif(Project p)
323 STRPTR file;
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) )
333 case 0: return 0;
334 case 1: return save_project(p, FALSE, FALSE);
337 /* User want to close this file */
338 return 1;
341 /*** Warn user that he is going to overwrite a file ***/
342 char warn_overwrite( STRPTR path )
344 APTR lock;
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);
356 return 1;
359 /*** Simple requester to ask user for a number ***/
360 int get_number( Project p, CONST_STRPTR title, LONG * result )
362 struct Window *win;
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,
372 WA_Width, 160,
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,
380 TAG_DONE)))
382 extern struct IntuiMessage msgbuf,*msg;
384 BusyWindow(Wnd);
385 /* Attach the simple OS1.3 compliant string gadget */
386 *LineNum = 0;
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 */
395 for(;;) {
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 )
406 case IDCMP_GADGETUP:
407 case IDCMP_CLOSEWINDOW: goto the_end;
411 /* Cleanup everything */
412 the_end: WakeUp(Wnd);
413 CloseWindow(win);
414 *result = SI.LongInt;
416 if( LineNum[0] != 0 ) return 1;
418 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
419 return 0;