Initial commit.
[amiga/xmodule.git] / Misc.c
1 /*
2 **      Misc.c
3 **
4 **      Copyright (C) 1993,94,95,96 Bernardo Innocenti
5 **
6 **      Parts of this file are:
7 **
8 **      Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
9 **              All Rights Reserved
10 **
11 **      Miscellaneus useful functions
12 */
13
14 #include <exec/ports.h>
15 #include <workbench/startup.h>
16
17 #include <proto/exec.h>
18 #include <proto/dos.h>
19 #include <proto/icon.h>
20 #include <proto/graphics.h>
21
22 #include "XModulePriv.h"
23 #include "Gui.h"
24
25
26 #if 0 /* --- This part has been removed --- */
27
28 /* Function pointers to Kickstart-sensitive RastPort query code */
29 ULONG (*ReadAPen)(struct RastPort *RPort);
30 ULONG (*ReadBPen)(struct RastPort *RPort);
31 ULONG (*ReadDrMd)(struct RastPort *RPort);
32
33
34
35 /* Local function prototypes */
36 static ULONG OldGetAPen (struct RastPort *RPort);
37 static ULONG OldGetBPen (struct RastPort *RPort);
38 static ULONG OldGetDrMd (struct RastPort *RPort);
39 static ULONG NewGetAPen (struct RastPort *RPort);
40 static ULONG NewGetBPen (struct RastPort *RPort);
41 static ULONG NewGetDrMd (struct RastPort *RPort);
42
43 #endif /* --- This part has been removed --- */
44
45
46
47 GLOBALCALL struct DiskObject *GetProgramIcon (void)
48
49 /* Get program associated icon.
50  * This function will fail if we are not a son of Workbench.
51  * The returned DiskObject must be freed by FreeDiskObject().
52  */
53 {
54         struct DiskObject *dobj;
55         BPTR olddir;
56
57         if (!WBenchMsg) return NULL;
58
59         olddir = CurrentDir (WBenchMsg->sm_ArgList->wa_Lock);
60         dobj = GetDiskObject (WBenchMsg->sm_ArgList->wa_Name);
61         CurrentDir (olddir);
62
63         return dobj;
64 }
65
66
67
68 GLOBALCALL struct Library *MyOpenLibrary (CONST_STRPTR name, ULONG ver)
69 {
70         struct Library *lib;
71         BPTR progdir = NULL;
72
73         while (!(lib = OpenLibrary (name, ver)))
74         {
75                 UBYTE path[PATHNAME_MAX];
76
77
78                 /* Search the library file in "PROGDIR:"... */
79
80                 strcpy (path, "PROGDIR:");
81                 AddPart (path, name, PATHNAME_MAX);
82                 if (lib = OpenLibrary (path, ver))
83                         break;
84
85                 strcpy (path, "PROGDIR:Libs");
86                 AddPart (path, name, PATHNAME_MAX);
87                 if (lib = OpenLibrary (path, ver))
88                         break;
89
90                 /* Tell the user we can't find this library anywhere... */
91                 if (!ShowRequest (MSG_OPENLIB_FAIL, MSG_RETRY_OR_CANCEL, name, ver))
92                         break;
93         }
94
95         if (progdir) UnLock (progdir);
96
97         return lib;
98 }
99
100
101
102 GLOBALCALL void CantOpenLib (CONST_STRPTR name, LONG ver)
103
104 /* Notify the user that a library didn't open */
105 {
106         if (ver)
107                 ShowRequest (MSG_OPENLIB_VER_FAIL, MSG_CONTINUE, name, ver);
108         else
109                 ShowRequest (MSG_OPENLIB_FAIL, MSG_CONTINUE, name);
110 }
111
112
113
114 GLOBALCALL void KillMsgPort (struct MsgPort *mp)
115
116 /* Reply all pending messages and call DeletePort() */
117 {
118         struct Message *msg;
119
120         Forbid();       /* is this really useful? */
121
122         /* Reply all pending Messages */
123         while (msg = GetMsg (mp))
124                 ReplyMsg (msg);
125
126         DeleteMsgPort (mp);
127
128         Permit();
129 }
130
131
132
133 GLOBALCALL struct TextAttr *CopyTextAttrPooled (void *pool, const struct TextAttr *source, struct TextAttr *dest)
134
135 /* Copy <source> textattr structure over <dest>, allocating and copying
136  * the ta_Name field.  <dest>->ta_Name if FreeVec()ed before
137  * allocating the new one.
138  *
139  * Returns: <dest> if everything was ok, NULL for failure.
140  */
141
142 {
143         FreeVecPooled (pool, dest->ta_Name);
144
145         memcpy (dest, source, sizeof (struct TextAttr));
146
147         if (dest->ta_Name = AllocVecPooled (pool, strlen (source->ta_Name) + 1))
148         {
149                 strcpy (dest->ta_Name, source->ta_Name);
150                 return dest;
151         }
152         return NULL;
153 }
154
155
156
157 GLOBALCALL UWORD CmpTextAttr (const struct TextAttr *ta1, const struct TextAttr *ta2)
158
159 /* Compares two TextAttr structures and returns 0 if they refer to
160  * the same font, a non-zero value otherwise.
161  */
162 {
163         if (ta1->ta_YSize == ta2->ta_YSize && ta1->ta_Style == ta2->ta_Style)
164         {
165                 if (!ta1->ta_Name && !ta2->ta_Name)
166                                 return 0;
167
168                 if (!ta1->ta_Name || !ta2->ta_Name)
169                                 return 1;
170
171                 if (!strcmp (ta1->ta_Name, ta2->ta_Name))
172                         return 0;
173         }
174
175         return 1;
176 }
177
178
179
180 /* More memory pools support */
181
182 #ifdef PORTABLE
183
184 GLOBCALL void *AllocVecPooled (void *pool, ULONG size)
185 {
186     void *mem;
187
188         size += 4;
189
190 #ifdef OS30_ONLY
191         if (mem = AllocPooled (pool, size))
192 #else
193         if (mem = AsmAllocPooled (pool, size))
194 #endif
195                 *((ULONG *)mem)++ = size;
196
197     return mem;
198 }
199
200
201
202 GLOBCALL void FreeVecPooled (void *pool, void *memory)
203 {
204     if (mem)
205     {
206                 --(((ULONG *)mem);
207 #ifdef OS30_ONLY
208                 FreePooled (pool, mem, *((ULONG *)mem));
209 #else
210                 AsmFreePooled (pool, mem, *((ULONG *)mem));
211 #endif
212     }
213 }
214
215
216
217 GLOBCALL void *CAllocVecPooled (void *pool, ULONG size)
218
219 {
220     void *mem;
221
222         size += 4;
223
224 #ifdef OS30_ONLY
225         if (mem = AllocPooled (pool, size))
226 #else
227         if (mem = AsmAllocPooled (pool, size))
228 #endif
229         {
230                 memset (mem, size, 0);
231                 *((ULONG *)mem)++ = size;
232         }
233
234     return mem;
235 }
236
237 #endif /* PORTABLE */
238
239
240
241 GLOBALCALL STRPTR DupStringPooled (void *pool, CONST_STRPTR source, STRPTR *dest)
242
243 /* Allocates a buffer big enough to fit the <source> string
244  * using AllocVecPooled() and then copies the contents of <source>
245  * there.  If the buffer pointed by <dest> is not NULL,
246  * DupStringPooled() will first check to see if <source> and
247  * <dest> are identical, in which case no new buffer will be
248  * allocated and the result will be FALSE.  Otherwise, <dest> will
249  * be deallocated and a new buffer will be allocated. Both <source> and <*dest>
250  * can be NULL.
251  *
252  * RESULT
253  *      Non-zero if <dest> has been reallocated, FALSE otherwise.
254  */
255 {
256         if (*dest)
257         {
258                 if (source)
259                 {
260                         if (!(strcmp (*dest, source)))
261                                 return NULL;
262                 }
263
264                 FreeVecPooled (pool, *dest);
265         }
266
267         if (source)
268         {
269                 if (*dest = AllocVecPooled (pool, strlen (source) + 1))
270                         strcpy (*dest, source);
271         }
272
273         return *dest;
274 }
275
276
277
278 GLOBALCALL void FilterName (STRPTR name)
279
280 /* Finds and blanks out invalid characters in a string.
281  * Will also strip blanks at the end.  Passing NULL is safe.
282  */
283 {
284         UWORD i = 0;
285
286         if (!name) return;
287
288         while (name[i])
289         {
290                 if (name[i] < ' ' ||
291                         (name[i] >'~' && name[i] < '¡'))
292                         name[i] = ' ';
293
294                 i++;
295         }
296
297         /* Kill blanks at the end of the string */
298         for (--i; i > 0 ; i--)
299                 if (name[i] == ' ') name[i] = '\0';
300                 else break;
301 }
302
303
304
305 GLOBALCALL LONG PutIcon (CONST_STRPTR source, CONST_STRPTR dest)
306
307 /* Add the <source> icon to <dest> file */
308 {
309         struct DiskObject *dobj;
310         UBYTE buf[PATHNAME_MAX];
311
312         /* We do not alter existing icons */
313         if (dobj = GetDiskObject (dest))
314         {
315                 FreeDiskObject (dobj);
316                 return RETURN_WARN;
317         }
318
319         /* Get source icon */
320
321         strcpy (buf, "PROGDIR:Icons");
322         AddPart (buf, source, PATHNAME_MAX);
323         if (!(dobj = GetDiskObject (buf)))
324         {
325                 strcpy (buf, "ENV:Sys");
326                 AddPart (buf, source, PATHNAME_MAX);
327                 if (!(dobj = GetDiskObject (buf)))
328                 {
329                         /* Get default project icon */
330                         dobj = GetDefDiskObject (WBPROJECT);
331                 }
332         }
333
334         if (dobj)
335         {
336                 dobj->do_CurrentX = dobj->do_CurrentY = NO_ICON_POSITION;
337
338                 if (!(dobj->do_DefaultTool[0]))
339                 {
340                         /* Get program path and store in icon's Default Tool */
341
342                         BPTR progdir;
343
344                         dobj->do_DefaultTool = NULL;
345
346                         if (WBenchMsg)  /* WB */
347                                 progdir = WBenchMsg->sm_ArgList->wa_Lock;
348                         else                    /* CLI */
349                                 progdir = GetProgramDir();
350
351                         if (progdir)
352                         {
353                                 if (NameFromLock (progdir, buf, PATHNAME_MAX))
354                                 {
355                                         UBYTE progname[32];
356
357                                         if (WBenchMsg)  /* WB */
358                                                 strncpy (progname, WBenchMsg->sm_ArgList->wa_Name, 32);
359                                         else                    /* CLI*/
360                                                 GetProgramName (progname, 32);
361
362                                         if(AddPart (buf, progname, PATHNAME_MAX))
363                                                 dobj->do_DefaultTool = buf;
364                                 }
365                         }
366                 }
367
368                 if (!dobj->do_DefaultTool) dobj->do_DefaultTool = BaseName;
369                 PutDiskObject (dest, dobj);
370                 FreeDiskObject (dobj);
371                 return RETURN_OK;
372         }
373
374         return RETURN_FAIL;
375 }
376
377
378
379 static ULONG MakeBackupName (STRPTR buf, CONST_STRPTR s, CONST_STRPTR tmpl, ULONG n)
380
381 /* DESCRIPTION
382  *      Subfunction for BackupFile() - Constructs a file name for the backup.
383  *      <tmpl> is the template to build the backup name.
384  *      Each occurence of the '#' character in the template is replaced with
385  *      an ASCII decimal representation of <n>. The '*' character is replaced
386  *      with the original filename <s>.
387  *
388  * RESULT
389  *      The result is stored in <buf>. Returns TRUE if at least one occurrence
390  *      of the '#' wildcard has been replaced, otherwise returns FALSE.
391  *
392  * BUGS
393  *      Does not check for buffer overflow.
394  *
395  */
396 {
397         BOOL wild_done = FALSE;
398         BOOL num_done = FALSE;
399
400         do
401         {
402                 if ((*tmpl == '*') && (!wild_done))
403                 {
404                         /* Copy file name */
405
406                         s = FilePart (s);
407                         while (*buf++ = *s++);
408                         --buf;
409
410                         wild_done = TRUE;
411                 }
412                 else if (*tmpl == '#')
413                 {
414                         /* Insert backup number */
415
416                         if (n > 9)
417                                 *buf++ = (n / 10) + '0';
418                         *buf++ = (n % 10) + '0';
419
420                         num_done = TRUE;
421                 }
422                 else if (*tmpl == '\\')
423                         /* Handle escape character */
424                         *buf++ = *++tmpl;
425                 else
426                         *buf++ = *tmpl;
427         }
428         while (*tmpl++);
429
430         return num_done;
431 }
432
433
434
435 GLOBALCALL LONG BackupFile (CONST_STRPTR src, CONST_STRPTR template, ULONG versions)
436
437 /* Creates backups of the given file */
438 {
439         UBYTE buf[PATHNAME_MAX], oldbuf[PATHNAME_MAX];
440         ULONG i;
441         BPTR lock, dir, olddir;
442
443         if (!(lock = Lock (src, ACCESS_READ)))
444                 return IoErr();
445
446         /* CD to source directory: needed for relative paths */
447         dir = ParentDir (lock);
448         olddir = CurrentDir (dir);
449
450
451         if (!MakeBackupName (buf, src, template, 1))
452         {
453                 /* Simple backup */
454                 DeleteFile (buf);
455         }
456         else
457         {
458                 /* Delete oldest backup if exists */
459
460                 MakeBackupName (buf, src, template, versions);
461                 DeleteFile (buf);
462
463                 /* Shift all others ahead... */
464
465                 for (i = versions; i > 0; --i)
466                 {
467                         strcpy (oldbuf, buf);
468                         MakeBackupName (buf, src, template, i);
469                         Rename (buf, oldbuf);
470
471                         DB (kprintf ("Backup name is: %s\n", buf));
472                 }
473         }
474
475         /* And finally move file to its backup location */
476         Rename (src, buf);
477
478         /* Restore old current directory */
479         CurrentDir (olddir);
480         UnLock (dir);
481         UnLock (lock);
482
483         return RETURN_OK;
484 }
485
486
487
488 #if 0 /* --- This part has been removed --- */
489
490 GLOBALCALL void InstallGfxFunctions (void)
491
492 /* Install the correct routines to query
493  * the rendering colours and drawing mode.
494  */
495 {
496         if(GfxBase->lib_Version >= 39)
497         {
498                 ReadAPen = NewGetAPen;
499                 ReadBPen = NewGetBPen;
500                 ReadDrMd = NewGetDrMd;
501         }
502         else
503         {
504                 ReadAPen = OldGetAPen;
505                 ReadBPen = OldGetBPen;
506                 ReadDrMd = OldGetDrMd;
507         }
508 }
509
510
511
512 /* OldGetAPen(struct RastPort *RPort):
513  *
514  *      Query the current primary rendering colour (old style).
515  */
516
517 static ULONG OldGetAPen (struct RastPort *RPort)
518 {
519         return((ULONG)RPort->FgPen);
520 }
521
522
523
524 /* OldGetBPen(struct RastPort *RPort):
525  *
526  *      Query the current seconary rendering colour (old style).
527  */
528
529 static ULONG OldGetBPen (struct RastPort *RPort)
530 {
531         return((ULONG)RPort->BgPen);
532 }
533
534
535
536 /* OldGetDrMd(struct RastPort *RPort):
537  *
538  *      Query the current drawing mode (old style).
539  */
540
541 static ULONG OldGetDrMd (struct RastPort *RPort)
542 {
543         return((ULONG)RPort->DrawMode);
544 }
545
546
547
548 /* NewGetAPen(struct RastPort *RPort):
549  *
550  *      Query the current primary rendering colour (new style).
551  */
552
553 static ULONG NewGetAPen (struct RastPort *RPort)
554 {
555         return(GetAPen (RPort));
556 }
557
558
559
560 /* NewGetBPen(struct RastPort *RPort):
561  *
562  *      Query the current seconary rendering colour (new style).
563  */
564
565 static ULONG NewGetBPen (struct RastPort *RPort)
566 {
567         return (GetBPen (RPort));
568 }
569
570
571
572 /* NewGetDrMd(struct RastPort *RPort):
573  *
574  *      Query the current drawing mode (new style).
575  */
576
577 static ULONG NewGetDrMd (struct RastPort *RPort)
578 {
579         return(GetDrMd (RPort));
580 }
581
582 #endif /* --- This part has been removed --- */