added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / workbench / tools / Edit / Utility.c
blobe45aefc629219f89ee75fcf4c87966a90fac801a
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 extern struct IntuitionBase *IntuitionBase;
24 extern ULONG err_time;
25 static UBYTE SPrintfBuf[80], *savea3;
27 /** SPrintf like routine **/
30 #ifdef __AROS__
31 #include <aros/asmcall.h>
33 AROS_UFH2(void, PutChProc,
34 AROS_UFHA(UBYTE, data, D0),
35 AROS_UFHA(STRPTR *, p, A3))
37 AROS_USERFUNC_INIT
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)
49 #endif
50 /* Can't use a3 ; compiler will restore register content on exit */
51 if( savea3 < SPrintfBuf + sizeof(SPrintfBuf) - 1 )
52 *savea3++ = data;
53 else *savea3 = 0;
55 #ifdef __AROS__
56 AROS_USERFUNC_EXIT
57 #endif
60 /** This is a very simplified routine, but takes only a few hundreed of bytes **/
61 STRPTR my_SPrintf(STRPTR fmt, APTR data)
63 savea3 = SPrintfBuf;
64 RawDoFmt(fmt, data, (void *)PutChProc, 0);
65 return SPrintfBuf;
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;
75 struct RastPort *RP;
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)
90 res->sa_Free = 0;
91 res->sa_NbArgs = 0;
92 if( nb == 0 ) {
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);
96 } else if( nb > 1 ) {
97 /* From CLI */
98 struct WBArg *new;
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;
103 res->sa_NbArgs = nb;
104 res->sa_Free = 1;
105 for(argv++; nb; new->wa_Name = *argv++, new->wa_Lock = cwd, new++, nb--);
106 CurrentDir( cwd );
111 /** Get the filename inside #include directive **/
112 STRPTR GetIncludeFile(Project prj, LINE * ln)
114 STRPTR p = ln->stream;
115 LONG i = ln->size;
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--);
124 if(i > 2)
126 extern UBYTE BufTxt[];
127 STRPTR dest = BufTxt;
128 UBYTE end = *p;
129 if(*p == '<') strcpy(BufTxt, "INCLUDE:"), dest+=8, end = '>';
130 else if(prj->path == NULL) BufTxt[0] = 0;
131 else {
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--);
136 *dest=0;
137 if(RETURN_OK == get_full_path(BufTxt, &dest))
138 return dest;
142 return NULL;
145 /* Generic list used ONLY as pointer */
146 typedef struct _list
148 struct _list *next, *prev;
149 } *list;
151 /*** Insert node Src after the node It ***/
152 void InsertAfter( list It,list Src )
154 register list L, Lp;
155 if(It)
157 Lp=It; L=Lp->next;
158 Src->next = L; Src->prev = Lp;
159 if( L ) L->prev = Src;
160 if( Lp ) Lp->next= Src;
161 } else
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)
176 STRPTR dst;
177 UWORD len;
178 if( ( dst = (STRPTR) AllocVec(len = strlen(dir) + strlen(file) + 2, MEMF_PUBLIC) ) )
179 strcpy(dst, dir), AddPart(dst, file, len);
180 return dst;
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)
195 if(ts != tab) {
196 int i;
197 for(i=0, tab=ts; i<sizeof(TabStop); i++)
199 TabStop[i] = tab;
200 if(tab==1) tab=ts; else tab--;
202 tab=ts;
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)
217 if( W ) {
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);
224 err_time = 0;
225 /* To be sure that mesage will be disappear one day */
226 ModifyIDCMP(W,W->IDCMPFlags | IDCMP_INTUITICKS);
227 } else puts(Msg);
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);
251 W->UserData = Msg;
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 **/
265 ULONG IDCMPFlags;
266 struct TagItem busy_pointer_tags[] =
268 {WA_BusyPointer,TRUE},
269 TAG_END
272 /*** Shutdown window IDCMP port ***/
273 void BusyWindow(struct Window *W)
275 if( W )
277 /* Store IDCMP flags and shutdown port */
278 IDCMPFlags = W->IDCMPFlags;
279 ModifyIDCMP(W,0);
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)
289 if( W )
290 ModifyIDCMP(W,IDCMPFlags),
291 ClearPointer(W);
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[];
301 STRPTR file;
302 ULONG bytes;
304 BusyWindow(Wnd);
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 ]);
312 WakeUp(Wnd);
315 /*** Avert user that its file has been modified ***/
316 char warn_modif(Project p)
318 STRPTR file;
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) )
328 case 0: return 0;
329 case 1: return save_project(p, FALSE, FALSE);
332 /* User want to close this file */
333 return 1;
336 /*** Avert user that he is going to overwrite a file ***/
337 char warn_overwrite( STRPTR path )
339 APTR lock;
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);
351 return 1;
354 /*** Simple requester to ask user for a number ***/
355 int get_number( Project p, CONST_STRPTR title, LONG * result )
357 struct Window *win;
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,
367 WA_Width, 160,
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,
375 TAG_DONE)))
377 extern struct IntuiMessage msgbuf,*msg;
379 BusyWindow(Wnd);
380 /* Attach the simple OS1.3 compliant string gadget */
381 *LineNum = 0;
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 */
390 for(;;) {
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 )
401 case IDCMP_GADGETUP:
402 case IDCMP_CLOSEWINDOW: goto the_end;
406 /* Cleanup everything */
407 the_end: WakeUp(Wnd);
408 CloseWindow(win);
409 *result = SI.LongInt;
411 if( LineNum[0] != 0 ) return 1;
413 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
414 return 0;