revert between 56095 -> 55830 in arch
[AROS.git] / workbench / tools / Edit / Utility.c
blob4608a53ade89488c195d3bb1786f1cdea05b2808
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[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 **/
36 #ifdef __AROS__
37 #include <aros/asmcall.h>
39 AROS_UFH2(void, PutChProc,
40 AROS_UFHA(UBYTE, data, D0),
41 AROS_UFHA(STRPTR *, p, A3))
43 AROS_USERFUNC_INIT
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)
55 #endif
56 /* Can't use a3 ; compiler will restore register content on exit */
57 if( savea3 < SPrintfBuf + sizeof(SPrintfBuf) - 1 )
58 *savea3++ = data;
59 else *savea3 = 0;
61 #ifdef __AROS__
62 AROS_USERFUNC_EXIT
63 #endif
66 /** This is a very simplified routine, but takes only a few hundred bytes **/
67 STRPTR my_SPrintf(STRPTR fmt, RAWARG data)
69 savea3 = SPrintfBuf;
70 RawDoFmt(fmt, (RAWARG)data, (void *)PutChProc, 0);
71 return SPrintfBuf;
74 /** Write column/line in top of window **/
75 void draw_info(Project p)
77 UpdateTitle(Wnd, 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)
98 res->sa_Free = 0;
99 res->sa_NbArgs = 0;
100 if( nb == 0 ) {
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 ) {
105 /* From CLI */
106 struct WBArg *new;
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;
111 res->sa_NbArgs = nb;
112 res->sa_Free = 1;
113 for(argv++; nb; new->wa_Name = *argv++, new->wa_Lock = cwd, new++, nb--);
114 CurrentDir( cwd );
119 /** Get the filename inside #include directive **/
120 STRPTR GetIncludeFile(Project prj, LINE * ln)
122 STRPTR p = ln->stream;
123 LONG i = ln->size;
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--);
132 if(i > 2)
134 extern UBYTE BufTxt[];
135 STRPTR dest = BufTxt;
136 UBYTE end = *p;
137 if(*p == '<') strcpy(BufTxt, "INCLUDE:"), dest+=8, end = '>';
138 else if(prj->path == NULL) BufTxt[0] = 0;
139 else {
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--);
144 *dest=0;
145 if(RETURN_OK == get_full_path(BufTxt, &dest))
146 return dest;
150 return NULL;
153 /* Generic list used ONLY as pointer */
154 typedef struct _list
156 struct _list *next, *prev;
157 } *list;
159 /*** Insert node Src after the node It ***/
160 void InsertAfter( list It,list Src )
162 register list L, Lp;
163 if(It)
165 Lp=It; L=Lp->next;
166 Src->next = L; Src->prev = Lp;
167 if( L ) L->prev = Src;
168 if( Lp ) Lp->next= Src;
169 } else
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)
184 STRPTR dst;
185 UWORD len;
186 if( ( dst = (STRPTR) AllocVec(len = strlen(dir) + strlen(file) + 2, MEMF_PUBLIC) ) )
187 strcpy(dst, dir), AddPart(dst, file, len);
188 return dst;
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)
203 if(ts != tab) {
204 int i;
205 for(i=0, tab=ts; i<sizeof(TabStop); i++)
207 TabStop[i] = tab;
208 if(tab==1) tab=ts; else tab--;
210 tab=ts;
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)
225 if( W ) {
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);
232 err_time = 0;
233 /* To be sure that message will disappear one day */
234 ModifyIDCMP(W,W->IDCMPFlags | IDCMP_INTUITICKS);
235 } else puts(Msg);
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);
259 W->UserData = Msg;
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 **/
273 ULONG IDCMPFlags;
274 struct TagItem busy_pointer_tags[] =
276 {WA_BusyPointer,TRUE},
277 {TAG_END,0}
280 /*** Shutdown window IDCMP port ***/
281 void BusyWindow(struct Window *W)
283 if( W )
285 /* Store IDCMP flags and shutdown port */
286 IDCMPFlags = W->IDCMPFlags;
287 ModifyIDCMP(W,0);
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)
297 if( W )
298 ModifyIDCMP(W,IDCMPFlags),
299 ClearPointer(W);
302 /* Information window about current project */
303 struct EasyStruct request;
305 /*** Show information window ***/
306 void show_info(Project p)
308 extern UBYTE WinTitle[];
309 STRPTR file;
310 ULONG bytes;
312 BusyWindow(Wnd);
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 ]);
321 WakeUp(Wnd);
324 /*** Warn user that file has been modified ***/
325 char warn_modif(Project p)
327 STRPTR file;
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) )
337 case 0: return 0;
338 case 1: return save_project(p, FALSE, FALSE);
341 /* User want to close this file */
342 return 1;
345 /*** Warn user that he is going to overwrite a file ***/
346 char warn_overwrite( STRPTR path )
348 APTR lock;
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);
360 return 1;
363 /*** Simple requester to ask user for a number ***/
364 int get_number( Project p, CONST_STRPTR title, LONG * result )
366 struct Window *win;
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,
376 WA_Width, 160,
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,
384 TAG_DONE)))
386 extern struct IntuiMessage msgbuf,*msg;
388 BusyWindow(Wnd);
389 /* Attach the simple OS1.3 compliant string gadget */
390 *LineNum = 0;
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 */
399 for(;;) {
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 )
410 case IDCMP_GADGETUP:
411 case IDCMP_CLOSEWINDOW: goto the_end;
415 /* Cleanup everything */
416 the_end: WakeUp(Wnd);
417 CloseWindow(win);
418 *result = SI.LongInt;
420 if( LineNum[0] != 0 ) return 1;
422 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
423 return 0;