using kprintf to output debug, which may be redirected to serial, is not a good idea...
[AROS-Contrib.git] / aminet / comm / term / term / Extras / Source / Tools.c
blob2092f443889a6b6863c8c049d7d7f54d30d2b8d3
1 /*
2 ** Tools.c
3 **
4 ** Miscellaneous support routines
5 **
6 ** Copyright © 1990-1996 by Olaf `Olsen' Barthel
7 ** All Rights Reserved
8 **
9 ** :ts=4
12 #ifndef _GLOBAL_H
13 #include "Global.h"
14 #endif
16 #ifdef __AROS__
17 # include <aros/asmcall.h>
18 # ifdef Dispatch
19 # undef Dispatch
20 # endif
21 # define Dispatch MyDispatch
22 AROS_UFP3(VOID, Dispatch,
23 AROS_UFPA(struct Hook * , UnusedHook , A0),
24 AROS_UFPA(struct RastPort * , RPort, A2),
25 AROS_UFPA(LayerMsg * , Bounds, A1));
26 #endif
28 /* Current timer state. */
30 STATIC BOOL TimerRunning;
32 /* ListViewStateFill(struct LVDrawMsg *Msg):
34 * Draw the ghosting pattern over a ghosted listview line.
37 VOID
38 ListViewStateFill(struct LVDrawMsg *Msg)
40 if(Msg->lvdm_State == LVR_SELECTEDDISABLED || Msg->lvdm_State == LVR_NORMALDISABLED)
42 struct RastPort *RPort = Msg->lvdm_RastPort;
43 ULONG Ghosting = 0x44441111;
45 SetABPenDrMd(RPort,Msg->lvdm_DrawInfo->dri_Pens[SHADOWPEN],0,JAM1);
47 SetAfPt(RPort,(UWORD *)&Ghosting,1);
49 RectFill(RPort,Msg->lvdm_Bounds.MinX,Msg->lvdm_Bounds.MinY,Msg->lvdm_Bounds.MaxX,Msg->lvdm_Bounds.MaxY);
51 SetAfPt(RPort,NULL,0);
55 /* EraseWindow(struct Window *Window):
57 * Fills the interior of a window in the background colour.
60 VOID
61 EraseWindow(struct Window *Window,UWORD *Pens)
63 LONG Left,Top,Right,Bottom;
65 Left = Window->BorderLeft;
66 Top = Window->BorderTop;
67 Right = Window->Width - (Window->BorderRight + 1);
68 Bottom = Window->Height - (Window->BorderBottom + 1);
70 if(Pens)
72 SetPens(RPort,Pens[BACKGROUNDPEN],0,JAM1);
74 RectFill(Window->RPort,Left,Top,Right,Bottom);
76 else
77 EraseRect(Window->RPort,Left,Top,Right,Bottom);
80 /* GetListMaxPen(UWORD *Pens):
82 * Calculates the maximum pen number index to be
83 * used for listview text rendering.
86 LONG
87 GetListMaxPen(UWORD *Pens)
89 STATIC BYTE PenTable[] =
91 TEXTPEN,
92 BACKGROUNDPEN,
93 FILLTEXTPEN,
94 FILLPEN,
95 SHADOWPEN,
96 HIGHLIGHTTEXTPEN,
99 LONG Max,Pen,i;
101 for(i = 0, Max = -1 ; i < NUM_ELEMENTS(PenTable) ; i++)
103 Pen = Pens[PenTable[i]];
105 if(Pen > Max)
106 Max = Pen;
109 return(Max);
112 /* FillBox(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height):
114 * Fill a rectangular area with the current foregroung colour.
117 VOID
118 FillBox(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height)
120 if(Width > 0 && Height > 0)
121 RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
124 VOID
125 FillWindowBox(struct Window *Window,LONG Left,LONG Top,LONG Width,LONG Height)
127 if(Left + Width > WindowWidth)
128 Width = WindowWidth - Left - 1;
130 if(Top + Height > WindowHeight)
131 Height = WindowHeight - Top - 1;
133 if(Width > 0 && Height > 0)
135 Left += Window->BorderLeft;
136 Top += Window->BorderTop;
138 RectFill(Window->RPort,Left,Top,Left + Width - 1,Top + Height - 1);
142 /* PlaceText(struct RastPort *RPort,LONG Left,LONG Top,STRPTR String,LONG Len):
144 * Print some text at a specific position.
147 VOID
148 PlaceText(struct RastPort *RPort,LONG Left,LONG Top,CONST_STRPTR String,LONG Len)
150 Move(RPort,Left,Top + RPort->TxBaseline);
151 Text(RPort,String,Len);
154 /* SetPens(struct RastPort *RPort,ULONG APen,ULONG BPen,ULONG DrMd):
156 * Set rendering attributes.
159 VOID
160 SetPens(struct RastPort *RPort,ULONG APen,ULONG BPen,ULONG DrMd)
162 if(Kick30)
163 SetABPenDrMd(RPort,APen,BPen,DrMd);
164 else
166 if(APen != RPort->FgPen)
167 SetAPen(RPort,APen);
169 if(BPen != RPort->BgPen)
170 SetBPen(RPort,BPen);
172 if(DrMd != RPort->DrawMode)
173 SetDrMd(RPort,DrMd);
177 /* Atol(STRPTR Buffer):
179 * Convert ASCII representation to long word.
182 LONG
183 Atol(CONST_STRPTR Buffer)
185 LONG Result;
187 StrToLong(Buffer,&Result);
189 return(Result);
192 /* StripSpaces(STRPTR String):
194 * Strip leading and trailing spaces from a string.
197 VOID
198 StripSpaces(STRPTR String)
200 if(String)
202 STRPTR To;
203 LONG Len;
205 To = String;
207 while(*String == ' ')
208 String++;
210 if(Len = strlen(String))
212 while(Len > 0 && String[Len - 1] == ' ')
213 Len--;
215 while(Len--)
216 *To++ = *String++;
219 *To = 0;
223 /* ReplaceWindowInfo(struct WindowInfo *NewInfo):
225 * Drop the window info into the right place.
228 VOID
229 ReplaceWindowInfo(struct WindowInfo *NewInfo)
231 LONG i;
233 ObtainSemaphore(&WindowInfoSemaphore);
235 for(i = 0 ; WindowInfoTable[i].ID != -1 ; i++)
237 if(WindowInfoTable[i].ID == NewInfo->ID)
239 CopyMem(NewInfo,&WindowInfoTable[i],sizeof(struct WindowInfo));
241 break;
245 ReleaseSemaphore(&WindowInfoSemaphore);
248 /* PutWindowInfo():
250 * Store window size and position relative to
251 * the main window.
254 VOID
255 PutWindowInfo(LONG ID,LONG Left,LONG Top,LONG Width,LONG Height)
257 LONG WindowLeft,WindowTop,WindowWidth,WindowHeight;
258 struct WindowInfo *Info = NULL;
259 ULONG IntuiLock;
260 LONG i;
262 ObtainSemaphore(&WindowInfoSemaphore);
264 for(i = 0 ; WindowInfoTable[i].ID != -1 ; i++)
266 if(WindowInfoTable[i].ID == ID)
268 Info = &WindowInfoTable[i];
270 break;
274 IntuiLock = LockIBase(0);
276 WindowLeft = Window->LeftEdge;
277 WindowTop = Window->TopEdge;
278 WindowWidth = Window->Width;
279 WindowHeight = Window->Height;
281 UnlockIBase(IntuiLock);
283 Info->WindowFlags = 0;
285 if(WindowWidth == Width && WindowLeft == Left)
286 Info->WindowFlags |= WC_EXPANDWIDTH;
287 else
289 if(Left == WindowLeft + WindowWidth)
290 Info->WindowFlags |= WC_ALIGNSIDE;
292 if(WindowLeft == Left)
293 Info->WindowFlags |= WC_ALIGNLEFT;
295 if(WindowLeft + WindowWidth == Left + Width)
296 Info->WindowFlags |= WC_ALIGNRIGHT;
299 if(WindowHeight == Height && WindowTop + Window->BorderTop == Top)
300 Info->WindowFlags |= WC_EXPANDHEIGHT;
301 else
303 if(Top == WindowTop + WindowHeight)
304 Info->WindowFlags |= WC_ALIGNBELOW;
306 if(Top == WindowTop + Window->BorderTop)
307 Info->WindowFlags |= WC_ALIGNTOP;
309 if(WindowTop + WindowHeight == Top + Height)
310 Info->WindowFlags |= WC_ALIGNBOTTOM;
313 Info->Left = Left;
314 Info->Top = Top;
315 Info->Width = Width;
316 Info->Height = Height;
318 ReleaseSemaphore(&WindowInfoSemaphore);
321 /* GetWindowInfo():
323 * Set the window size and position in relation to
324 * the main window.
327 VOID
328 GetWindowInfo(LONG ID,LONG *Left,LONG *Top,LONG *Width,LONG *Height,LONG DefWidth,LONG DefHeight)
330 LONG WindowLeft = 0,WindowTop = 0,WindowWidth = 0,WindowHeight = 0;
331 struct WindowInfo *Info;
332 ULONG IntuiLock;
333 LONG i;
335 SafeObtainSemaphoreShared(&WindowInfoSemaphore);
337 Info = NULL;
339 for(i = 0 ; WindowInfoTable[i].ID != -1 ; i++)
341 if(WindowInfoTable[i].ID == ID)
343 Info = &WindowInfoTable[i];
345 break;
349 if(Info && ID == WINDOW_MAIN)
351 *Left = Info->Left;
352 *Top = Info->Top;
353 *Width = Info->Width;
354 *Height = Info->Height;
356 else
358 if(Window)
360 IntuiLock = LockIBase(0);
362 WindowLeft = Window->LeftEdge;
363 WindowTop = Window->TopEdge;
364 WindowWidth = Window->Width;
365 WindowHeight = Window->Height;
367 UnlockIBase(IntuiLock);
369 if(DefWidth && DefWidth < WindowWidth / 2)
370 DefWidth = WindowWidth / 2;
372 if(DefHeight && DefHeight < WindowHeight / 2)
373 DefHeight = WindowHeight / 2;
376 if(*Width)
378 if(Info->Width)
379 *Left = Info->Left;
380 else
381 *Left = WindowLeft + (WindowWidth - *Width) / 2;
383 else
385 if(DefWidth && !Info->Width)
387 *Width = DefWidth;
388 *Left = WindowLeft + (WindowWidth - *Width) / 2;
390 else
392 if(Info->Width)
394 *Width = Info->Width;
395 *Left = Info->Left;
397 else
399 *Width = WindowWidth;
400 *Left = WindowLeft;
405 if(*Height)
407 if(Info->Height)
408 *Top = Info->Top;
409 else
410 *Top = WindowTop + (WindowHeight - *Height) / 2;
412 else
414 if(DefHeight && !Info->Height)
416 *Height = DefHeight;
417 *Top = WindowTop + (WindowHeight - *Height) / 2;
419 else
421 if(Info->Height)
423 *Height = Info->Height;
424 *Top = Info->Top;
426 else
428 *Height = WindowHeight;
429 *Top = WindowTop;
434 if(Info->WindowFlags & WC_ALIGNSIDE)
435 *Left = WindowLeft + WindowWidth;
437 if(Info->WindowFlags & WC_ALIGNBELOW)
438 *Top = WindowTop + WindowHeight;
440 if(Info->WindowFlags & WC_ALIGNLEFT)
441 *Left = WindowLeft;
443 if(Info->WindowFlags & WC_ALIGNTOP)
444 *Top = WindowTop;
446 if(Info->WindowFlags & WC_ALIGNRIGHT)
447 *Left = WindowLeft + WindowWidth - *Width;
449 if(Info->WindowFlags & WC_ALIGNBOTTOM)
450 *Top = WindowTop + WindowHeight - *Height;
452 if(Info->WindowFlags & WC_EXPANDWIDTH)
453 *Width = WindowWidth;
455 if(Info->WindowFlags & WC_EXPANDHEIGHT)
456 *Height = WindowHeight;
458 if(*Top == WindowTop && *Left == WindowLeft)
460 LONG TitleHeight = Window->BorderTop;
462 if(*Height == WindowHeight)
463 *Height -= TitleHeight;
465 *Top += TitleHeight;
469 ReleaseSemaphore(&WindowInfoSemaphore);
472 /* GetBitMapDepth(struct BitMap *BitMap):
474 * Return the depth of a BitMap.
477 LONG
478 GetBitMapDepth(struct BitMap *BitMap)
480 LONG Depth;
482 if(Kick30)
483 Depth = (LONG)GetBitMapAttr(BitMap,BMA_DEPTH);
484 else
485 Depth = BitMap->Depth;
487 if(Depth > 8)
488 Depth = 8;
490 return(Depth);
493 /* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
495 * Get screen DPI resolution values.
498 VOID
499 GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI)
501 struct DisplayInfo DisplayInfo;
503 *X_DPI = *Y_DPI = 72;
505 if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
507 if(DisplayInfo.PixelSpeed && DisplayInfo.Resolution.x && DisplayInfo.Resolution.y)
509 *X_DPI = (35 * 140) / DisplayInfo.PixelSpeed;
510 *Y_DPI = (*X_DPI * DisplayInfo.Resolution.x) / DisplayInfo.Resolution.y;
515 /* AddProtection(STRPTR FileName,ULONG Mask):
517 * Set bits in the protection mask of a file.
520 VOID
521 AddProtection(STRPTR Name,ULONG Mask)
523 BPTR FileLock;
524 D_S(struct FileInfoBlock,FileInfo);
526 if(FileLock = Lock(Name,ACCESS_READ))
528 if(Examine(FileLock,FileInfo))
530 UnLock(FileLock);
532 if(Mask == FIBF_EXECUTE)
533 Mask |= FileInfo->fib_Protection & ~(FIBF_OTR_EXECUTE|FIBF_GRP_EXECUTE);
534 else
535 Mask |= FileInfo->fib_Protection;
537 SetProtection(Name,Mask);
539 else
540 UnLock(FileLock);
544 /* GetPubScreenName(struct Screen *Screen,STRPTR Name):
546 * Get the name of a public screen.
549 BOOL
550 GetPubScreenName(struct Screen *Screen,STRPTR Name)
552 struct List *PubScreenList;
553 struct PubScreenNode *ScreenNode;
554 BOOL GotIt;
556 PubScreenList = LockPubScreenList();
558 for(ScreenNode = (struct PubScreenNode *)PubScreenList->lh_Head, GotIt = FALSE ; !GotIt && ScreenNode->psn_Node.ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode->psn_Node.ln_Succ)
560 if(ScreenNode->psn_Screen == Screen)
562 strcpy(Name,ScreenNode->psn_Node.ln_Name);
563 GotIt = TRUE;
567 UnlockPubScreenList();
569 return(GotIt);
572 /* InitSinglePort(struct MsgPort *Port):
574 * Initialize a plain MsgPort (as created on the stack) for
575 * usage. Don't try this at home, kids!
578 VOID
579 InitSinglePort(struct MsgPort *Port)
581 memset(Port,0,sizeof(struct MsgPort));
583 Port->mp_Flags = PA_SIGNAL;
584 Port->mp_SigBit = SIGB_SINGLE;
585 Port->mp_SigTask = FindTask(NULL);
587 NewList(&Port->mp_MsgList);
590 /* GoodStream(BPTR Stream):
592 * Check to see whether the current input file
593 * is an interactive stream.
596 BOOL
597 GoodStream(BPTR Stream)
599 if(!Stream)
600 Stream = Input();
602 if(Stream)
604 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
606 if(Handle->fh_Type)
608 if(IsInteractive(Stream))
609 return(TRUE);
613 return(FALSE);
616 /* GetProgramIcon():
618 * Try to find the icon of the program.
621 struct DiskObject *
622 GetProgramIcon()
624 struct DiskObject *Icon = NULL;
626 /* Run from Workbench? */
628 if(WBenchMsg)
630 /* Sanity check. */
632 if(WBenchMsg->sm_ArgList)
634 /* Yet another sanity check. */
636 if(WBenchMsg->sm_ArgList->wa_Name)
638 /* Try to find the icon in the current directory. */
640 if(Icon = GetDiskObjectNew(WBenchMsg->sm_ArgList->wa_Name))
642 if(Icon->do_Type != WBTOOL)
644 FreeDiskObject(Icon);
646 Icon = NULL;
650 if(!Icon)
652 BPTR NewLock;
654 /* Move to the directory the
655 * program was run from.
658 if(NewLock = Lock("PROGDIR:",ACCESS_READ))
660 BPTR OldLock;
662 OldLock = CurrentDir(NewLock);
664 /* Try to fetch the icon, use the
665 * default name if necessary.
668 if(Icon = GetDiskObjectNew(WBenchMsg->sm_ArgList->wa_Name))
670 if(Icon->do_Type != WBTOOL)
672 FreeDiskObject(Icon);
674 Icon = NULL;
678 if(!Icon)
680 if(Icon = GetDiskObjectNew("term"))
682 if(Icon->do_Type != WBTOOL)
684 FreeDiskObject(Icon);
686 Icon = NULL;
691 CurrentDir(OldLock);
693 UnLock(NewLock);
700 /* Still no success. */
702 if(!Icon)
704 /* Use the default names. */
706 if(Icon = GetDiskObjectNew("term"))
708 if(Icon->do_Type != WBTOOL)
710 FreeDiskObject(Icon);
712 Icon = NULL;
716 if(!Icon)
718 if(Icon = GetDiskObjectNew("PROGDIR:term"))
720 if(Icon->do_Type != WBTOOL)
722 FreeDiskObject(Icon);
724 Icon = NULL;
730 return(Icon);
733 /* GetPenIndex(LONG Pen):
735 * Get the table index corresponding to an on-screen
736 * text rendering pen.
739 LONG
740 GetPenIndex(LONG Pen)
742 LONG i,Result = 0;
744 for(i = 0 ; i < 16 ; i++)
746 if(MappedPens[0][i] == Pen)
748 Result = i;
749 break;
753 return(Result);
756 /* GetScreenWidth(struct Window *Window):
758 * Query the current screen width.
761 LONG
762 GetScreenWidth(struct Window *Window)
764 if(Window)
766 if(Window->Width > ScreenWidth || Window->LeftEdge < -Window->WScreen->LeftEdge || Window->LeftEdge + Window->WScreen->LeftEdge + Window->Width > ScreenWidth)
767 return(ScreenWidth);
768 else
769 return(Window->Width - (Window->BorderLeft + Window->BorderRight));
771 else
772 return(ScreenWidth);
775 /* GetScreenHeight(struct Window *Window):
777 * Query the current screen height.
780 LONG
781 GetScreenHeight(struct Window *Window)
783 if(Window)
785 if(Window->Height > ScreenHeight || Window->TopEdge < -Window->WScreen->TopEdge || Window->TopEdge + Window->WScreen->TopEdge + Window->Height > ScreenHeight)
786 return(ScreenHeight);
787 else
788 return(Window->Height - (Window->BorderTop + Window->BorderBottom));
790 else
791 return(ScreenHeight);
794 /* GetLeft(struct Screen *Screen):
796 * Get the screen left edge.
799 STATIC LONG
800 GetLeft(struct Screen *Screen)
802 if(Screen->LeftEdge >= 0)
803 return(0);
804 else
805 return(-Screen->LeftEdge);
808 /* GetScreenLeft(struct Window *Window):
810 * Query the current screen left edge.
813 LONG
814 GetScreenLeft(struct Window *Window)
816 if(Window)
818 if(Window->Width > ScreenWidth || Window->LeftEdge < -Window->WScreen->LeftEdge || Window->LeftEdge + Window->WScreen->LeftEdge + Window->Width > ScreenWidth)
819 return(GetLeft(Window->WScreen));
820 else
821 return(Window->LeftEdge + Window->BorderLeft);
823 else
825 struct Screen *PubScreen = LockPubScreen(NULL);
826 LONG Result;
828 Result = GetLeft(PubScreen ? PubScreen : SharedScreen);
830 UnlockPubScreen(NULL,PubScreen);
832 return(Result);
836 /* OldGetAPen(struct RastPort *RPort):
838 * Query the current primary rendering colour (old style).
841 ULONG
842 OldGetAPen(struct RastPort *RPort)
844 return((ULONG)RPort->FgPen);
847 /* OldGetBPen(struct RastPort *RPort):
849 * Query the current seconary rendering colour (old style).
852 ULONG
853 OldGetBPen(struct RastPort *RPort)
855 return((ULONG)RPort->BgPen);
858 /* OldGetDrMd(struct RastPort *RPort):
860 * Query the current drawing mode (old style).
863 ULONG
864 OldGetDrMd(struct RastPort *RPort)
866 return((ULONG)RPort->DrawMode);
869 /* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
871 * Set the rendering plane mask (old style).
874 ULONG
875 OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
877 if(UseMasking)
878 RPort->Mask = Mask;
880 return((ULONG)1);
883 /* OldGetWrMsk(struct RastPort *RPort):
885 * Get the rendering plane mask (old style).
888 ULONG
889 OldGetWrMsk(struct RastPort *RPort)
891 return(RPort->Mask);
894 /* NewGetAPen(struct RastPort *RPort):
896 * Query the current primary rendering colour (new style).
899 ULONG
900 NewGetAPen(struct RastPort *RPort)
902 return(GetAPen(RPort));
905 /* NewGetBPen(struct RastPort *RPort):
907 * Query the current seconary rendering colour (new style).
910 ULONG
911 NewGetBPen(struct RastPort *RPort)
913 return(GetBPen(RPort));
916 /* NewGetDrMd(struct RastPort *RPort):
918 * Query the current drawing mode (new style).
921 ULONG
922 NewGetDrMd(struct RastPort *RPort)
924 return(GetDrMd(RPort));
927 /* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
929 * Set the rendering plane mask (new style).
932 ULONG
933 NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
935 if(UseMasking)
936 return(SetWriteMask(RPort,Mask));
937 else
938 return((ULONG)1);
941 /* NewGetWrMsk(struct RastPort *RPort):
943 * Get the rendering plane mask (new style).
946 ULONG
947 NewGetWrMsk(struct RastPort *RPort)
949 ULONG Mask;
951 Mask = (ULONG)~0;
953 GetRPAttrs(RPort,
954 RPTAG_WriteMask,&Mask,
955 TAG_DONE);
957 return(Mask);
960 /* SetWait(struct Window *Window):
962 * Set the busy wait mouse pointer.
965 VOID
966 SetWait(struct Window *Window)
968 if(GTLayoutBase)
969 LT_LockWindow(Window);
972 /* ClrWait(struct Window *Window):
974 * Remove the busy wait mouse pointer.
977 VOID
978 ClrWait(struct Window *Window)
980 if(GTLayoutBase)
981 LT_UnlockWindow(Window);
984 /* GetModeName(ULONG Mode):
986 * Get the name of a display mode.
989 VOID
990 GetModeName(ULONG Mode,STRPTR Buffer,LONG BufferSize)
992 struct NameInfo NameInfo;
994 if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
995 LimitedStrcpy(BufferSize,Buffer,NameInfo.Name);
996 else
998 struct DimensionInfo DimensionInfo;
1000 if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
1002 STRPTR MonitorName;
1004 switch(Mode & MONITOR_ID_MASK)
1006 case NTSC_MONITOR_ID:
1008 MonitorName = "NTSC:";
1009 break;
1011 case PAL_MONITOR_ID:
1013 MonitorName = "PAL:";
1014 break;
1016 case VGA_MONITOR_ID:
1018 MonitorName = "VGA:";
1019 break;
1021 case A2024_MONITOR_ID:
1023 MonitorName = "A2024:";
1024 break;
1026 default:
1028 MonitorName = "";
1029 break;
1032 LimitedSPrintf(BufferSize,Buffer,"%s%ldx%ld",MonitorName,DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1,DimensionInfo.TxtOScan.MaxY - DimensionInfo.TxtOScan.MinY + 1);
1034 else
1035 LimitedStrcpy(BufferSize,Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
1039 /* ModeOkay(ULONG ID):
1041 * Checks whether a display mode ID will do for deep
1042 * screen bitmaps.
1045 BOOL
1046 ModeOkay(ULONG ID)
1048 struct DimensionInfo DimensionInfo;
1050 if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
1052 if(DimensionInfo.MaxDepth >= 4)
1053 return(TRUE);
1056 return(FALSE);
1059 /* ExtractString():
1061 * Extracts a string from a list separated by `|' characters.
1064 STRPTR
1065 ExtractString(STRPTR String,STRPTR Destination,BOOL ReturnEnd)
1067 STRPTR OldString;
1069 if(ReturnEnd)
1070 OldString = NULL;
1071 else
1072 OldString = String;
1074 while(*String)
1076 if(*String == '|')
1078 *Destination = 0;
1080 String++;
1082 if(*String)
1083 return(String);
1084 else
1085 return(OldString);
1087 else
1088 *Destination++ = *String++;
1091 *Destination = 0;
1093 return(OldString);
1096 /* RemoveGetNext(struct Node *Node):
1098 * Remove a node from a list and return the `next'
1099 * node to take its place.
1102 struct Node *
1103 RemoveGetNext(struct Node *Node)
1105 struct Node *Next;
1107 /* Does the node have a successor? */
1109 if(Node->ln_Succ->ln_Succ)
1110 Next = Node->ln_Succ;
1111 else
1113 /* Does it have a predecessor? */
1115 if(Node->ln_Pred->ln_Pred)
1116 Next = Node->ln_Pred;
1117 else
1118 Next = NULL;
1121 /* Remove the old node. */
1123 Remove(Node);
1125 /* And return the node to take its place. */
1127 return(Next);
1130 /* GetListSize(struct List *List):
1132 * Determine the number of entries in a list.
1135 LONG
1136 GetListSize(struct List *List)
1138 struct Node *Node;
1139 LONG i;
1141 for(Node = List->lh_Head, i = 0 ; Node->ln_Succ ; Node = Node->ln_Succ, i++);
1143 return(i);
1146 /* GetListNode(LONG Offset,struct List *List):
1148 * Return the n-th Node entry in a standard exec list.
1151 struct Node *
1152 GetListNode(LONG Offset,struct List *List)
1154 struct Node *Node;
1155 LONG Index;
1157 for(Node = List->lh_Head, Index = 0 ; Node->ln_Succ ; Node = Node->ln_Succ, Index++)
1159 if(Index == Offset)
1160 return(Node);
1163 return(NULL);
1166 /* CreateNode(STRPTR Name):
1168 * Put a name string into a list node.
1171 struct Node *
1172 CreateNode(STRPTR Name)
1174 struct Node *Node;
1176 if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(Name) + 1,MEMF_ANY))
1177 strcpy(Node->ln_Name = (STRPTR)(Node + 1),Name);
1179 return(Node);
1182 /* CreateNodeArgs(STRPTR Format,...):
1184 * Put a name string into a list node, varargs version.
1187 struct Node *
1188 CreateNodeArgs(STRPTR Format,...)
1190 UBYTE LocalBuffer[256];
1191 struct Node *Node;
1192 va_list VarArgs;
1194 va_start(VarArgs,Format);
1195 LimitedVSPrintf(sizeof(LocalBuffer),LocalBuffer,Format,VarArgs);
1196 va_end(VarArgs);
1198 if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(LocalBuffer) + 1,MEMF_ANY))
1199 strcpy(Node->ln_Name = (STRPTR)(Node + 1),LocalBuffer);
1201 return(Node);
1204 /* FormatAppend(STRPTR String,STRPTR Format,...):
1206 * Appends a formatted string to another string.
1209 VOID
1210 FormatAppend(STRPTR String,STRPTR Format,...)
1212 va_list VarArgs;
1214 String += strlen(String);
1216 va_start(VarArgs,Format);
1217 VSPrintf(String,Format,VarArgs);
1218 va_end(VarArgs);
1221 /* FreeList(struct List *List):
1223 * Remove all nodes from the list
1224 * and free them on the way.
1227 VOID
1228 FreeList(struct List *List)
1230 if(List)
1232 struct Node *Node;
1234 while(Node = RemHead(List))
1235 FreeVecPooled(Node);
1239 /* GetNodeOffset(struct Node *Node,struct List *List):
1241 * Scan a list for a certain node and return
1242 * its position.
1245 LONG
1246 GetNodeOffset(struct Node *ListNode,struct List *List)
1248 if(ListNode && List)
1250 struct Node *Node;
1251 LONG Offset;
1253 for(Node = List->lh_Head, Offset = 0 ; Node->ln_Succ ; Node = Node->ln_Succ, Offset++)
1255 if(Node == ListNode)
1256 return(Offset);
1260 return(-1);
1263 /* MoveList(struct List *From,struct List *To):
1265 * Move the contents of a list to a different list.
1268 VOID
1269 MoveList(struct List *From,struct List *To)
1271 struct Node *Node;
1273 while(Node = RemHead(From))
1274 AddTail(To,Node);
1277 /* CreateList():
1279 * Create a small, empty list.
1282 struct List *
1283 CreateList()
1285 struct List *List;
1287 if(List = (struct List *)AllocVecPooled(sizeof(struct MinList),MEMF_ANY))
1288 NewList(List);
1290 return(List);
1293 /* DeleteList():
1295 * Free the contents of a list and the list itself.
1298 VOID
1299 DeleteList(struct List *List)
1301 if(List)
1303 struct Node *Node,*Next;
1305 for(Node = List->lh_Head ; Next = Node->ln_Succ ; Node = Next)
1306 FreeVecPooled(Node);
1308 FreeVecPooled(List);
1312 /* MoveNode(struct List *List,struct Node *Node,LONG How):
1314 * Move a list node somewhere.
1317 VOID
1318 MoveNode(struct List *List,struct Node *Node,LONG How)
1320 switch(How)
1322 case MOVE_HEAD:
1324 if(Node != List->lh_Head)
1326 Remove(Node);
1328 AddHead(List,Node);
1331 break;
1333 case MOVE_PRED:
1335 if(Node != List->lh_Head)
1337 struct Node *Other;
1339 Other = Node->ln_Pred->ln_Pred;
1341 Remove(Node);
1343 Insert(List,Node,Other);
1346 break;
1348 case MOVE_SUCC:
1350 if(Node != List->lh_TailPred)
1352 struct Node *Other;
1354 Other = Node->ln_Succ;
1356 Remove(Node);
1358 Insert(List,Node,Other);
1361 break;
1363 case MOVE_TAIL:
1365 if(Node != List->lh_TailPred)
1367 Remove(Node);
1369 AddTail(List,Node);
1372 break;
1376 /* LogAction(STRPTR String,...):
1378 * Write an action to the default log file.
1381 VOID
1382 LogAction(CONST_STRPTR String,...)
1384 if(Config->CaptureConfig->LogActions && Config->CaptureConfig->LogFileName[0])
1386 UBYTE DummyBuffer[512];
1387 BPTR File;
1388 BOOL Created;
1390 va_list VarArgs;
1392 /* Build a valid string. */
1394 va_start(VarArgs,String);
1395 LimitedVSPrintf(sizeof(DummyBuffer),DummyBuffer,String,VarArgs);
1396 va_end(VarArgs);
1398 /* Open the log file. */
1400 if(File = OpenToAppend(Config->CaptureConfig->LogFileName,&Created))
1402 if(Created)
1403 FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
1406 /* The file is open, build the date/time string and
1407 * write the log action.
1410 if(File)
1412 UBYTE DateBuffer[40],
1413 TimeBuffer[40];
1414 struct DateTime DateTime;
1416 DateStamp(&DateTime.dat_Stamp);
1418 DateTime.dat_Format = FORMAT_DEF;
1419 DateTime.dat_Flags = 0;
1420 DateTime.dat_StrDay = NULL;
1421 DateTime.dat_StrDate = DateBuffer;
1422 DateTime.dat_StrTime = TimeBuffer;
1424 if(DateToStr(&DateTime))
1426 StripSpaces(TimeBuffer);
1428 FPrintf(File,"%-9s %8s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
1431 /* Done! */
1433 Close(File);
1438 /* GetString(STRPTR Prompt,STRPTR Buffer):
1440 * Get a string from the user, very much the same as xpr_gets.
1443 BOOL
1444 GetString(BOOL LoadGadget,BOOL Password,LONG MaxChars,CONST_STRPTR Prompt,STRPTR Buffer)
1446 enum { GAD_OK=1,GAD_CANCEL,GAD_STRING };
1448 struct LayoutHandle *Handle;
1449 UBYTE LocalBuffer[256];
1450 BOOL Success = FALSE;
1452 if(!MaxChars)
1453 MaxChars = sizeof(LocalBuffer) - 1;
1455 if(MaxChars > sizeof(LocalBuffer) - 1)
1457 CopyMem(Buffer,LocalBuffer,sizeof(LocalBuffer) - 1);
1459 LocalBuffer[sizeof(LocalBuffer) - 1] = 0;
1461 MaxChars = sizeof(LocalBuffer) - 1;
1463 else
1464 strcpy(LocalBuffer,Buffer);
1466 if(!Prompt)
1467 Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
1469 if(Handle = LT_CreateHandleTags(Window->WScreen,
1470 LAHN_LocaleHook, &LocaleHook,
1471 TAG_DONE))
1473 struct Window *PanelWindow;
1475 LT_New(Handle,
1476 LA_Type, VERTICAL_KIND,
1477 TAG_DONE);
1479 LT_New(Handle,
1480 LA_Type, VERTICAL_KIND,
1481 LA_LabelText, Prompt,
1482 TAG_DONE);
1484 if(Password)
1486 LT_New(Handle,
1487 LA_Type, PASSWORD_KIND,
1488 LA_STRPTR, LocalBuffer,
1489 LA_ID, GAD_STRING,
1490 LA_Chars, 40,
1491 GTST_MaxChars, MaxChars,
1492 TAG_DONE);
1494 else
1496 LT_New(Handle,
1497 LA_Type, STRING_KIND,
1498 LA_STRPTR, LocalBuffer,
1499 LA_ID, GAD_STRING,
1500 LA_Chars, 60,
1501 LAST_Picker, LoadGadget,
1502 TAG_DONE);
1505 LT_EndGroup(Handle);
1508 LT_New(Handle,
1509 LA_Type,VERTICAL_KIND,
1510 TAG_DONE);
1512 LT_New(Handle,
1513 LA_Type, XBAR_KIND,
1514 LAXB_FullSize, TRUE,
1515 TAG_DONE);
1517 LT_EndGroup(Handle);
1520 LT_New(Handle,LA_Type,HORIZONTAL_KIND,
1521 LAGR_SameSize, TRUE,
1522 LAGR_Spread, TRUE,
1523 TAG_DONE);
1525 LT_New(Handle,
1526 LA_Type, BUTTON_KIND,
1527 LA_LabelID, MSG_TERMXPR_OKAY_GAD,
1528 LA_ID, GAD_OK,
1529 LABT_ReturnKey, TRUE,
1530 LABT_ExtraFat, TRUE,
1531 TAG_DONE);
1533 LT_New(Handle,
1534 LA_Type, BUTTON_KIND,
1535 LA_LabelID, MSG_GLOBAL_CANCEL_GAD,
1536 LA_ID, GAD_CANCEL,
1537 LABT_EscKey, TRUE,
1538 LABT_ExtraFat, TRUE,
1539 TAG_DONE);
1541 LT_EndGroup(Handle);
1545 if(PanelWindow = LT_Build(Handle,
1546 LAWN_TitleID, MSG_GLOBAL_ENTER_TEXT_TXT,
1547 LAWN_HelpHook, &GuideHook,
1548 LAWN_Parent, Window,
1549 WA_DepthGadget, TRUE,
1550 WA_DragBar, TRUE,
1551 WA_RMBTrap, TRUE,
1552 WA_Activate, TRUE,
1553 WA_SimpleRefresh, TRUE,
1554 TAG_DONE))
1556 struct IntuiMessage *Message;
1557 BOOL Done = FALSE;
1558 ULONG MsgClass;
1559 UWORD MsgCode;
1560 struct Gadget *MsgGadget;
1562 LT_Activate(Handle,GAD_STRING);
1564 PushWindow(PanelWindow);
1566 LT_ShowWindow(Handle,TRUE);
1570 if(Wait(PORTMASK(PanelWindow->UserPort) | SIG_BREAK) & SIG_BREAK)
1571 break;
1573 while(Message = (struct IntuiMessage *)LT_GetIMsg(Handle))
1575 MsgClass = Message->Class;
1576 MsgCode = Message->Code;
1577 MsgGadget = (struct Gadget *)Message->IAddress;
1579 LT_ReplyIMsg(Message);
1581 if(MsgClass == IDCMP_GADGETUP)
1583 switch(MsgGadget->GadgetID)
1585 case GAD_STRING:
1587 if(MsgCode == '\r')
1589 LT_UpdateStrings(Handle);
1591 strcpy(Buffer,LocalBuffer);
1593 Success = Done = TRUE;
1595 LT_PressButton(Handle,GAD_OK);
1598 break;
1600 case GAD_OK:
1602 LT_UpdateStrings(Handle);
1604 strcpy(Buffer,LocalBuffer);
1606 Success = Done = TRUE;
1607 break;
1609 case GAD_CANCEL:
1611 Done = TRUE;
1612 break;
1616 if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget->GadgetID == GAD_STRING)
1618 UBYTE DummyBuffer[MAX_FILENAME_LENGTH];
1619 struct FileRequester *FileRequest;
1621 strcpy(DummyBuffer,LocalBuffer);
1623 if(FileRequest = OpenSingleFile(PanelWindow,LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),NULL,NULL,DummyBuffer,sizeof(DummyBuffer)))
1625 FreeAslRequest(FileRequest);
1627 LT_SetAttributes(Handle,GAD_STRING,
1628 GTST_String, DummyBuffer,
1629 TAG_DONE);
1634 while(!Done);
1636 PopWindow();
1639 LT_DeleteHandle(Handle);
1642 return(Success);
1645 /* WakeUp(struct Window *Window,LONG Sound):
1647 * Pop a window to the front and alert the user.
1650 VOID
1651 WakeUp(struct Window *Window,LONG Sound)
1653 if(Window)
1655 if(Config->MiscConfig->AlertMode == ALERT_SCREEN || Config->MiscConfig->AlertMode == ALERT_BEEP_SCREEN)
1657 if(Window->WScreen->LeftEdge > 0)
1659 if(Window->WScreen->TopEdge > 0)
1660 MoveScreen(Window->WScreen,-Window->WScreen->LeftEdge,-Window->WScreen->TopEdge);
1661 else
1662 MoveScreen(Window->WScreen,-Window->WScreen->LeftEdge,0);
1664 else
1666 if(Window->WScreen->TopEdge > 0)
1667 MoveScreen(Window->WScreen,0,-Window->WScreen->TopEdge);
1670 WindowToFront(Window);
1672 ScreenToFront(Window->WScreen);
1676 if(Sound != SOUND_BELL || Config->MiscConfig->AlertMode == ALERT_BEEP || Config->MiscConfig->AlertMode == ALERT_BEEP_SCREEN)
1677 SoundPlay(Sound);
1680 /* BlockWindows():
1682 * Block the main window and the status window (i.e. disable
1683 * the menu and attach a wait pointer).
1686 VOID
1687 BlockWindows()
1689 if(!(BlockNestCount++))
1691 LT_LockWindow(Window);
1692 LT_LockWindow(StatusWindow);
1693 LT_LockWindow(FastWindow);
1694 LT_LockWindow(MatrixWindow);
1696 WeAreBlocking = TRUE;
1698 SetQueueDiscard(SpecialQueue,TRUE);
1700 GhostCursor();
1704 /* ReleaseWindows():
1706 * Reenable the menus and clear the wait pointer.
1709 VOID
1710 ReleaseWindows()
1712 if(BlockNestCount == 1)
1714 LT_UnlockWindow(Window);
1715 LT_UnlockWindow(StatusWindow);
1716 LT_UnlockWindow(FastWindow);
1717 LT_UnlockWindow(MatrixWindow);
1719 WeAreBlocking = FALSE;
1721 SetQueueDiscard(SpecialQueue,FALSE);
1723 if(Window)
1725 Forbid();
1727 if(Window->Flags & WFLG_WINDOWACTIVE)
1728 NormalCursor();
1730 Permit();
1734 if(BlockNestCount)
1735 BlockNestCount--;
1739 /* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
1741 * Read a few bytes from a file (à la gets).
1744 LONG
1745 LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
1747 STATIC UBYTE Data[1024];
1748 STATIC LONG ReadIndex,ReadLen;
1750 LONG BytesRead = 0;
1752 if(File)
1754 LONG i;
1756 for(i = 0 ; i < MaxChars ; i++)
1758 if(ReadIndex >= ReadLen)
1760 ReadLen = Read(File,Data,sizeof(Data));
1762 ReadIndex = 0;
1764 if(ReadLen <= 0)
1766 Buffer[i] = 0;
1767 break;
1771 BytesRead++;
1773 if((Buffer[i] = Data[ReadIndex++]) == '\n')
1775 Buffer[i + 1] = 0;
1777 break;
1781 else
1782 ReadIndex = ReadLen = 0;
1784 return(BytesRead);
1787 /* GetBaudRate(STRPTR Buffer):
1789 * Calculate the baud rate contained in a connect string.
1792 LONG
1793 GetBaudRate(STRPTR Buffer)
1795 UBYTE LocalBuffer[40];
1796 LONG Rate,i,j;
1798 for(i = j = 0 ; i < strlen(Buffer) ; i++)
1800 if(Buffer[i] == ' ')
1801 continue;
1802 else
1804 if(Buffer[i] >= '0' && Buffer[i] <= '9')
1805 LocalBuffer[j++] = Buffer[i];
1806 else
1807 break;
1811 LocalBuffer[j] = 0;
1813 if(StrToLong(LocalBuffer,&Rate) > 0)
1815 if(Rate > 0)
1816 return(Rate);
1819 return(0);
1822 /* GetFileSize(STRPTR Name):
1824 * Simple routine to return the size of a file in
1825 * bytes.
1828 LONG
1829 GetFileSize(CONST_STRPTR Name)
1831 BPTR FileLock;
1832 LONG FileSize = 0;
1833 D_S(struct FileInfoBlock,FileInfo);
1835 if(FileLock = Lock(Name,ACCESS_READ))
1837 if(Examine(FileLock,FileInfo))
1839 if(FileInfo->fib_DirEntryType < 0)
1840 FileSize = FileInfo->fib_Size;
1843 UnLock(FileLock);
1846 return(FileSize);
1849 /* PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height):
1851 * Put back the default values for the requesters to open.
1854 VOID
1855 PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height)
1857 if(Config->MiscConfig->RequesterMode != REQUESTERMODE_IGNORE && (!Config->MiscConfig->RequesterWidth || !Config->MiscConfig->RequesterHeight))
1859 if(!Reference)
1860 Reference = Window;
1862 Config->MiscConfig->RequesterLeft = Left - Reference->LeftEdge;
1863 Config->MiscConfig->RequesterTop = Top - Reference->TopEdge;
1864 Config->MiscConfig->RequesterWidth = Width;
1865 Config->MiscConfig->RequesterHeight = Height;
1869 /* GetDimensionTags(struct Window *Reference,struct TagItem *Tags):
1871 * Fills an array of tagitems with the dimensions of an asl requester
1872 * to be opened.
1875 struct TagItem *
1876 GetDimensionTags(struct Window *Reference,struct TagItem *Tags)
1878 if(Config->MiscConfig->RequesterMode == REQUESTERMODE_IGNORE || Config->MiscConfig->RequesterWidth < 1 || Config->MiscConfig->RequesterHeight < 1)
1880 STATIC ULONG Done = TAG_DONE;
1882 return((struct TagItem *)&Done);
1884 else
1886 LONG Left,Top,Width,Height;
1888 if(!Reference)
1889 Reference = Window;
1891 if(Config->MiscConfig->RequesterMode == REQUESTERMODE_CENTRE)
1893 Left = Reference->LeftEdge + (Reference->Width - Config->MiscConfig->RequesterWidth) / 2;
1894 Top = Reference->TopEdge + (Reference->Height - Config->MiscConfig->RequesterHeight) / 2;
1896 else
1898 Left = Config->MiscConfig->RequesterLeft + Reference->LeftEdge;
1899 Top = Config->MiscConfig->RequesterTop + Reference->TopEdge;
1902 Width = Config->MiscConfig->RequesterWidth;
1903 Height = Config->MiscConfig->RequesterHeight;
1905 Tags[0].ti_Tag = ASL_LeftEdge;
1906 Tags[0].ti_Data = Left;
1907 Tags[1].ti_Tag = ASL_TopEdge;
1908 Tags[1].ti_Data = Top;
1909 Tags[2].ti_Tag = ASL_Width;
1910 Tags[2].ti_Data = Width;
1911 Tags[3].ti_Tag = ASL_Height;
1912 Tags[3].ti_Data = Height;
1913 Tags[4].ti_Tag = TAG_DONE;
1915 return(Tags);
1919 /* ShowRequest(struct Window *Window,CONST_STRPTR Text,STRPTR CONST_Gadgets,...):
1921 * Really quite simple varargs version of Intuition's
1922 * EasyRequest requester.
1925 LONG
1926 ShowRequest(struct Window *Window,CONST_STRPTR Text,CONST_STRPTR Gadgets,...)
1928 struct EasyStruct Easy;
1929 LONG i,GadgetCount;
1931 for(i = GadgetCount = 0 ; i < strlen(Gadgets) ; i++)
1933 if(Gadgets[i] == '|')
1934 GadgetCount++;
1937 /* Standard data. */
1939 Easy.es_StructSize = sizeof(struct EasyStruct);
1940 Easy.es_Flags = 0;
1941 Easy.es_Title = LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
1942 Easy.es_TextFormat = Text;
1943 Easy.es_GadgetFormat = Gadgets;
1945 AROS_SLOWSTACKFORMAT_PRE_USING(Gadgets, Text);
1946 if(GadgetCount)
1948 LONG Result;
1950 if(GTLayoutBase)
1951 LT_LockWindow(Window);
1953 /* Use the argument array to build the
1954 * requester and display it.
1956 Result = EasyRequestArgs(Window,&Easy,NULL,AROS_SLOWSTACKFORMAT_ARG(Gadgets));
1959 if(GTLayoutBase)
1960 LT_UnlockWindow(Window);
1962 return(Result);
1964 else
1966 struct Window *ReqWindow;
1968 if(GTLayoutBase)
1969 LT_LockWindow(Window);
1971 if(ReqWindow = BuildEasyRequestArgs(Window,&Easy,IDCMP_RAWKEY,AROS_SLOWSTACKFORMAT_ARG(Gadgets)))
1973 ULONG IDCMP;
1974 LONG Result;
1976 FOREVER
1978 WaitPort(ReqWindow->UserPort);
1980 IDCMP = 0;
1982 Result = SysReqHandler(ReqWindow,&IDCMP,FALSE);
1984 if(!Result || (Result == -2 && !(IDCMP & IDCMP_RAWKEY)))
1985 break;
1988 FreeSysRequest(ReqWindow);
1991 if(GTLayoutBase)
1992 LT_UnlockWindow(Window);
1995 AROS_SLOWSTACKFORMAT_POST(Gadgets);
1997 return(0);
2000 /* CloseWindowSafely(struct Window *Window):
2002 * Close a window freeing all messages pending at
2003 * its user port (taken from example source code
2004 * published once upon a time in Amiga Mail).
2007 VOID
2008 CloseWindowSafely(struct Window *Window)
2010 Forbid();
2012 if(Window->UserPort)
2014 struct Node *Node,*Next;
2016 for(Node = Window->UserPort->mp_MsgList.lh_Head ; Next = Node->ln_Succ ; Node = Next)
2018 if(((struct IntuiMessage *)Node)->IDCMPWindow == Window)
2020 Remove(Node);
2021 ReplyMsg((struct Message *)Node);
2025 Window->UserPort = NULL;
2028 ModifyIDCMP(Window,0);
2030 Permit();
2032 LT_DeleteWindowLock(Window);
2034 CloseWindow(Window);
2037 /* DelayTime(LONG Secs,LONG Micros):
2039 * Delay for a given period of time.
2042 VOID
2043 DelayTime(LONG Secs,LONG Micros)
2045 StopTime();
2047 if(Secs || Micros)
2049 StartTime(Secs,Micros);
2051 WaitTime();
2055 /* WaitTime():
2057 * Wait for a pending time request to finish.
2060 VOID
2061 WaitTime()
2063 if(TimerRunning)
2065 TimerRunning = FALSE;
2067 WaitIO((struct IORequest *)TimeRequest);
2071 /* StopTime():
2073 * Stop the running timer.
2076 VOID
2077 StopTime()
2079 if(TimerRunning)
2081 if(!CheckIO((struct IORequest *)TimeRequest))
2082 AbortIO((struct IORequest *)TimeRequest);
2084 WaitIO((struct IORequest *)TimeRequest);
2088 /* StartTime(LONG Secs,LONG Micros):
2090 * Start the timer asynchronously.
2093 VOID
2094 StartTime(LONG Secs,LONG Micros)
2096 StopTime();
2098 if(Secs || Micros)
2100 TimeRequest->tr_node.io_Command = TR_ADDREQUEST;
2101 TimeRequest->tr_time.tv_secs = Secs;
2102 TimeRequest->tr_time.tv_micro = Micros;
2104 ClrSignal(SIG_TIMER);
2106 SendIO((struct IORequest *)TimeRequest);
2108 TimerRunning = TRUE;
2112 /* GetEnvDOS(STRPTR Name,STRPTR Buffer):
2114 * Get the contents of a vanilla AmigaDOS environment
2115 * variable.
2118 BOOL
2119 GetEnvDOS(STRPTR Name,STRPTR Buffer,LONG BufferSize)
2121 if(GetVar(Name,Buffer,256,0) >= 0)
2122 return(TRUE);
2123 else
2125 Buffer[0] = 0;
2127 return(FALSE);
2131 /* SetEnvDOS(STRPTR Name,STRPTR Value):
2133 * Set the contents of a vanilla AmigaDOS environment
2134 * variable.
2137 BOOL
2138 SetEnvDOS(STRPTR Name,STRPTR Value)
2140 if(SetVar(Name,Value,-1,GVF_SAVE_VAR))
2142 /* Ouch! Bug in dos.library V39! GVF_SAVE_VAR doesn't
2143 * work unless GVF_GLOBAL_ONLY is set as well.
2146 /* if(Kick30)*/
2147 /* return(TRUE);*/
2148 /* else*/
2150 UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
2151 BOOL Result = FALSE;
2153 strcpy(LocalBuffer,"ENVARC:");
2155 if(AddPart(LocalBuffer,FilePart(Name),sizeof(LocalBuffer)))
2157 BPTR FileHandle;
2159 if(!(FileHandle = Open(LocalBuffer,MODE_NEWFILE)))
2160 Result = FALSE;
2161 else
2163 LONG Length = strlen(Value);
2165 if(Write(FileHandle,Value,Length) == Length)
2166 Result = TRUE;
2168 Close(FileHandle);
2172 return(Result);
2176 return(FALSE);
2179 /* BumpWindow(struct Window *SomeWindow):
2181 * Bring a window to the front (and shift the screen
2182 * back to its initial position).
2185 VOID
2186 BumpWindow(struct Window *SomeWindow)
2188 if(SomeWindow)
2190 if(SomeWindow->WScreen->LeftEdge > 0)
2192 if(SomeWindow->WScreen->TopEdge > 0)
2193 MoveScreen(SomeWindow->WScreen,-SomeWindow->WScreen->LeftEdge,-SomeWindow->WScreen->TopEdge);
2194 else
2195 MoveScreen(SomeWindow->WScreen,-SomeWindow->WScreen->LeftEdge,0);
2197 else
2199 if(SomeWindow->WScreen->TopEdge > 0)
2200 MoveScreen(SomeWindow->WScreen,0,-SomeWindow->WScreen->TopEdge);
2203 ScreenToFront(SomeWindow->WScreen);
2205 ActivateWindow(SomeWindow);
2209 /* PushWindow(struct Window *Window):
2211 * Push/PopWindow implement a single lifo window stack
2212 * which always updates the window to activate when
2213 * LSHIFT+RSHIFT+RETURN is pressed. This routine will
2214 * push a window on the stack.
2217 VOID
2218 PushWindow(struct Window *Window)
2220 if(WindowStackPtr < 5)
2222 WindowStack[WindowStackPtr++] = Window;
2224 TopWindow = Window;
2228 /* PopWindow():
2230 * Remove topmost window from window stack.
2233 VOID
2234 PopWindow()
2236 if(WindowStackPtr > 0)
2238 WindowStackPtr--;
2240 if(WindowStackPtr)
2241 TopWindow = WindowStack[WindowStackPtr - 1];
2242 else
2243 TopWindow = Window;
2247 /* SplitFileName():
2249 * Split a full file name into a file and a drawer name.
2252 VOID
2253 SplitFileName(STRPTR FullName,STRPTR *FileName,STRPTR DrawerName)
2255 if(FilePart(FullName) == FullName)
2257 *DrawerName = 0;
2258 *FileName = FullName;
2260 else
2262 STRPTR Dummy;
2264 strcpy(DrawerName,FullName);
2266 Dummy = PathPart(DrawerName);
2268 *Dummy = 0;
2270 *FileName = FilePart(FullName);
2274 /* BackfillRoutine():
2276 * Window layer backfill routine.
2279 #ifndef __AROS__
2280 VOID SAVE_DS ASM
2281 BackfillRoutine(REG(a0) struct Hook *UnusedHook,REG(a2) struct RastPort *RPort,REG(a1) LayerMsg *Bounds)
2282 #else
2283 AROS_UFH3(VOID, BackfillRoutine,
2284 AROS_UFHA(struct Hook * , UnusedHook , A0),
2285 AROS_UFHA(struct RastPort * , RPort, A2),
2286 AROS_UFHA(LayerMsg * , Bounds, A1))
2287 #endif
2289 #ifdef __AROS__
2290 AROS_USERFUNC_INIT
2291 #endif
2292 struct RastPort RastPort;
2294 CopyMem(RPort,&RastPort,sizeof(struct RastPort));
2295 RastPort.Layer = NULL;
2297 RPort = &RastPort;
2299 SetAPen(RPort,Pens[BACKGROUNDPEN]);
2300 SetDrMd(RPort,JAM2);
2302 RectFill(RPort,Bounds->Bounds.MinX,Bounds->Bounds.MinY,Bounds->Bounds.MaxX,Bounds->Bounds.MaxY);
2303 #ifdef __AROS__
2304 AROS_USERFUNC_EXIT
2305 #endif
2308 struct NameSegment
2310 UBYTE String[63],
2311 Separator;
2314 STATIC STRPTR
2315 FindChar(STRPTR Template,LONG c)
2317 while(*Template)
2319 if(*Template == c)
2320 return(Template);
2321 else
2322 Template++;
2325 return(NULL);
2328 STATIC UBYTE *
2329 GetNameSegment(struct NameSegment *NameSegment,UBYTE *cp,LONG i)
2331 UBYTE *xp = NameSegment[i].String;
2333 while (*cp && !FindChar("._+-,@~=",*cp))
2334 *xp++ = *cp++;
2336 *xp = '\0';
2338 NameSegment[i].Separator = *cp;
2340 if (*cp)
2341 cp++;
2343 if(NameSegment[i].String[0] || NameSegment[i].Separator)
2344 return(cp);
2345 else
2346 return(NULL);
2349 STATIC VOID
2350 CopyNameSegment(struct NameSegment *NameSegment,UBYTE *Destination,LONG Zap)
2352 UBYTE *cp = Destination,*xp;
2354 for(xp = NameSegment[0].String ; *xp ; )
2355 *cp++ = *xp++;
2357 if(NameSegment[0].Separator)
2359 LONG i;
2361 *cp++ = NameSegment[0].Separator;
2363 for(i = Zap + 1 ; ; i++)
2365 for(xp = NameSegment[i].String ; *xp ; )
2366 *cp++ = *xp++;
2368 if(NameSegment[i].Separator)
2369 *cp++ = NameSegment[i].Separator;
2370 else
2372 if(!NameSegment[i].String[0])
2373 break;
2378 *cp = 0;
2381 /* ShrinkName():
2383 * Shrink a file name down to a number of characters, if
2384 * possible preserving the structure of the name. Algorithm
2385 * courtesy of the "shrink" program by Simon Brown,
2386 * Edinburgh University.
2389 UBYTE *
2390 ShrinkName(UBYTE *Source,UBYTE *Destination,LONG MaxLength,BOOL FixSuffix)
2392 #define MAXSEGS 10
2394 struct NameSegment NameSegment[MAXSEGS];
2396 LONG i,NumSegments,SuffixLength,Remainder,Delete,Total,Zap = 0;
2397 UBYTE *OldPtr = (UBYTE *)Source;
2399 for(i = 0 ; i < MAXSEGS && (OldPtr = GetNameSegment(NameSegment,OldPtr,i)) ; i++);
2401 if(i < MAXSEGS)
2403 NumSegments = i - 1;
2405 if((NumSegments * 2) < MaxLength)
2407 SuffixLength = strlen(NameSegment[NumSegments].String);
2409 if(SuffixLength > MaxLength - NumSegments - 1)
2411 SuffixLength = MaxLength - (2 * NumSegments) - 1;
2413 NameSegment[NumSegments].String[SuffixLength - 1] = 0;
2415 else
2417 if (SuffixLength + NumSegments > MaxLength-NumSegments-1)
2418 Zap = NumSegments - (MaxLength-SuffixLength)/2;
2421 if(NumSegments >= 1)
2423 for(i = Zap + 1 ; i <= NumSegments ; i++)
2425 if(NameSegment[i].Separator)
2426 SuffixLength++;
2429 if(NameSegment[0].Separator)
2430 SuffixLength++;
2432 Remainder = MaxLength - SuffixLength;
2434 Delete = Remainder / NumSegments;
2436 Total = SuffixLength;
2438 for(i = Zap + 1 ; i < NumSegments ; i++)
2440 NameSegment[i].String[Delete] = 0;
2442 Total += Delete;
2445 NameSegment[0].String[MaxLength - Total] = 0;
2448 CopyNameSegment(NameSegment,Destination,Zap);
2450 else
2451 strcpy(Destination,Source);
2453 else
2454 strcpy(Destination,Source);
2456 if(FixSuffix)
2458 BOOL GotDot = FALSE;
2459 LONG Len = strlen(Destination),Dots;
2461 for(i = Dots = 0 ; i < Len ; i++)
2463 if(Destination[i] == '.')
2464 Dots++;
2467 if(!Dots)
2469 if(Len < 4)
2470 strcat(Destination,".___");
2471 else
2472 Destination[Len - 4] = '.';
2475 for(i = Len - 1 ; i >= 0 ; i--)
2477 if(Destination[i] == '.')
2479 if(GotDot)
2480 Destination[i] = '_';
2481 else
2482 GotDot = TRUE;
2485 if(Destination[i] == '\\')
2486 Destination[i] = '-';
2490 return(Destination);
2493 /* BuildFontName(STRPTR Destination,STRPTR Name,LONG Size):
2495 * Build a font name and size string from given
2496 * information (raw name and size).
2499 VOID
2500 BuildFontName(STRPTR Destination,LONG DestinationSize,STRPTR Name,LONG Size)
2502 UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
2503 LONG Len;
2505 Name = FilePart(Name);
2506 Len = strlen(Name);
2508 if(Len > 5 && !Stricmp(&Name[Len - 5],".font"))
2510 strcpy(LocalBuffer,Name);
2512 LocalBuffer[Len - 5] = 0;
2514 Name = LocalBuffer;
2517 LimitedSPrintf(DestinationSize,Destination,"%s %ld",Name,Size);
2520 /* FixName(STRPTR Name):
2522 * Build a correct AmigaDOS filename.
2525 VOID
2526 FixName(STRPTR Name)
2528 LONG NameLen = strlen(Name),i;
2530 /* Replace special characters. */
2532 for(i = 0 ; i < NameLen ; i++)
2534 switch(Name[i])
2536 case ' ':
2538 Name[i] = '_';
2539 break;
2541 case ':':
2543 Name[i] = '.';
2544 break;
2546 case '/':
2548 Name[i] = '\\';
2549 break;
2551 case '\"':
2553 Name[i] = '\'';
2554 break;
2558 /* Truncate the name. */
2560 if(NameLen > 31)
2561 Name[31] = 0;
2564 /* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
2566 * Display an error message, in human readable form if possible.
2569 VOID
2570 ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String)
2572 STATIC LONG LocalErrors[][2] =
2574 { ERR_SAVE_ERROR, MSG_ERR_COULD_NOT_SAVE_FILE_TXT, },
2575 { ERR_LOAD_ERROR, MSG_ERR_COULD_NOT_LOAD_FILE_TXT, },
2576 { ERR_OUTDATED, MSG_ERR_OUTDATED_TXT, },
2577 { ERR_EXECUTE_ERROR, MSG_ERR_COULD_NOT_EXECUTE_PROGRAM_TXT, },
2579 { ERR_FILE_NOT_FOUND, MSG_VERIFY_NO_FILE_TXT, },
2580 { ERR_DRAWER_NOT_FOUND, MSG_VERIFY_DRAWER_NOT_FOUND_TXT, },
2581 { ERR_PROGRAM_NOT_FOUND, MSG_VERIFY_NO_PROGRAM_TXT, },
2582 { ERR_NOT_A_FILE, MSG_VERIFY_DRAWER_NOT_A_FILE_TXT, },
2583 { ERR_NOT_A_DRAWER, MSG_VERIFY_FILE_NOT_A_DRAWER_TXT, },
2585 { IFFERR_NOMEM, MSG_IFFERR_NOMEM_TXT, },
2586 { IFFERR_READ, MSG_IFFERR_READ_TXT, },
2587 { IFFERR_WRITE, MSG_IFFERR_WRITE_TXT, },
2588 { IFFERR_SEEK, MSG_IFFERR_SEEK_TXT, },
2589 { IFFERR_MANGLED, MSG_IFFERR_MANGLED_TXT, },
2590 { IFFERR_NOTIFF, MSG_IFFERR_NOTIFF_TXT, },
2592 { 0 },
2595 UBYTE LocalBuffer1[FAULT_MAX],LocalBuffer2[FAULT_MAX];
2596 CONST_STRPTR PrimaryError,SecondaryError;
2598 PrimaryError = SecondaryError = NULL;
2600 if(Primary)
2602 LONG i;
2604 for(i = 0 ; LocalErrors[i][0] ; i++)
2606 if(LocalErrors[i][0] == Primary)
2608 PrimaryError = LocaleString(LocalErrors[i][1]);
2610 break;
2614 if(!PrimaryError)
2616 if(Fault(Primary,NULL,LocalBuffer1,sizeof(LocalBuffer1)))
2617 PrimaryError = LocalBuffer1;
2621 if(Secondary)
2623 LONG i;
2625 for(i = 0 ; LocalErrors[i][0] ; i++)
2627 if(LocalErrors[i][0] == Secondary)
2629 SecondaryError = LocaleString(LocalErrors[i][1]);
2631 break;
2635 if(!SecondaryError)
2637 if(Fault(Secondary,NULL,LocalBuffer2,sizeof(LocalBuffer2)))
2638 SecondaryError = LocalBuffer2;
2642 if(PrimaryError)
2644 if(String)
2645 ShowRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),String,SecondaryError);
2646 else
2647 ShowRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),SecondaryError);
2651 struct List *
2652 BuildModeList(LONG *Index,ULONG DisplayMode,MODEFILTER ModeFilter,APTR UserData)
2654 struct List *List;
2655 LONG Count = 0;
2657 *Index = 0;
2659 if(List = CreateList())
2661 struct DisplayInfo DisplayInfo;
2662 ULONG SomeMode = INVALID_ID;
2664 while((SomeMode = NextDisplayInfo(SomeMode)) != INVALID_ID)
2666 if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,SomeMode))
2668 if((DisplayInfo.PropertyFlags & DIPF_IS_WB) && !(DisplayInfo.NotAvailable & ~DI_AVAIL_NOTWITHGENLOCK))
2670 UBYTE ModeNameBuffer[DISPLAYNAMELEN + 1];
2671 struct ModeNode *ModeNode;
2673 if(ModeFilter)
2675 if(!(*ModeFilter)(SomeMode,UserData))
2676 continue;
2679 GetModeName(SomeMode,ModeNameBuffer,sizeof(ModeNameBuffer));
2681 if(ModeNode = (struct ModeNode *)AllocVecPooled(sizeof(struct ModeNode) + strlen(ModeNameBuffer) + 1,MEMF_ANY))
2683 strcpy(ModeNode->Node.ln_Name = (STRPTR)(ModeNode + 1),ModeNameBuffer);
2685 ModeNode->DisplayID = SomeMode;
2687 AddTail(List,(struct Node *)ModeNode);
2689 Count++;
2696 if(Count)
2698 struct ModeNode *Node,*Next;
2700 for(Node = (struct ModeNode *)List->lh_Head ; Node->Node.ln_Succ ; Node = (struct ModeNode *)Node->Node.ln_Succ)
2702 if(!(Node->DisplayID & MONITOR_ID_MASK))
2704 for(Next = (struct ModeNode *)List->lh_Head ; Next->Node.ln_Succ ; Next = (struct ModeNode *)Next->Node.ln_Succ)
2706 if((Node->DisplayID & ~MONITOR_ID_MASK) == (Next->DisplayID & ~MONITOR_ID_MASK) && Next != Node)
2707 Node->DisplayID = INVALID_ID;
2711 for(Next = (struct ModeNode *)List->lh_Head ; Next->Node.ln_Succ ; Next = (struct ModeNode *)Next->Node.ln_Succ)
2713 if(Node->DisplayID == Next->DisplayID && Next != Node)
2714 Next->DisplayID = INVALID_ID;
2718 for(Node = (struct ModeNode *)List->lh_Head ; Next = (struct ModeNode *)Node->Node.ln_Succ ; Node = Next)
2720 if(Node->DisplayID == INVALID_ID)
2722 Count--;
2724 Remove((struct Node *)Node);
2726 FreeVecPooled(Node);
2731 if(Count)
2733 struct ModeNode *Node,*Next;
2735 for(Count = 0, Node = (struct ModeNode *)List->lh_Head ; Next = (struct ModeNode *)Node->Node.ln_Succ ; Node = Next)
2737 if(Node->DisplayID == DisplayMode)
2739 *Index = Count;
2741 break;
2745 return(List);
2747 else
2749 DeleteList(List);
2751 return(NULL);
2755 /* IsAssign(STRPTR Name):
2757 * Does a name refer to an assignment?
2760 BOOL
2761 IsAssign(CONST_STRPTR Name)
2763 LONG NameLen = strlen(Name) - 1;
2764 BOOL Result = FALSE;
2766 /* Does it end with a colon? */
2768 if(Name[NameLen] == ':')
2770 struct DosList *DosList;
2771 STRPTR AssignName;
2773 /* Lock the list of assignments for reading. */
2775 DosList = LockDosList(LDF_ASSIGNS | LDF_READ);
2777 /* Scan the list... */
2779 while(DosList = NextDosEntry(DosList,LDF_ASSIGNS))
2781 /* Convert the name from icky
2782 * BCPL to `C' style string.
2785 AssignName = (STRPTR)BADDR(DosList->dol_Name);
2787 /* Does the name length match? */
2789 if(AssignName[0] == NameLen)
2791 /* Does the name itself match? */
2793 if(!Strnicmp(&AssignName[1],Name,NameLen))
2795 Result = TRUE;
2797 break;
2802 /* Unlock the list of assignments. */
2804 UnLockDosList(LDF_ASSIGNS | LDF_READ);
2807 /* Return the result. */
2809 return(Result);
2812 /* LockInAssign(BPTR TheLock,STRPTR TheAssignment):
2814 * Check if a file lock is part of an assignment.
2817 BOOL
2818 LockInAssign(BPTR TheLock,STRPTR TheAssignment)
2820 struct DevProc *DevProc = NULL;
2821 struct MsgPort *FileSysTask = GetFileSysTask();
2822 BOOL Result = FALSE;
2825 /* Loop until all assignments are
2826 * processed.
2831 /* Get the default filesystem task
2832 * in case we stumble upon NULL
2833 * directory locks.
2836 if(DevProc = GetDeviceProc(TheAssignment,DevProc))
2838 /* Set the default filesystem task. */
2840 SetFileSysTask(DevProc->dvp_Port);
2842 /* Is the lock on the list? */
2844 if(SameLock(DevProc->dvp_Lock,TheLock) == LOCK_SAME)
2845 Result = TRUE;
2847 else
2848 break;
2850 while(DevProc && (DevProc->dvp_Flags & DVPF_ASSIGN) && !Result);
2852 /* Reset the default filesystem task. */
2854 SetFileSysTask(FileSysTask);
2856 /* Free device process data. */
2858 if(DevProc)
2859 FreeDeviceProc(DevProc);
2861 return(Result);
2864 /* DeleteBitMap(struct BitMap *BitMap):
2866 * Delete a bitmap created by CreateBitMap().
2869 VOID
2870 DeleteBitMap(struct BitMap *BitMap)
2872 if(BitMap)
2874 WaitBlit();
2876 if(Kick30)
2877 FreeBitMap(BitMap);
2878 else
2880 LONG i,*Sizes,Width,Height;
2882 Sizes = &((LONG *)BitMap)[-2];
2884 Width = Sizes[0];
2885 Height = Sizes[1];
2887 for(i = 0 ; i < BitMap->Depth ; i++)
2888 FreeRaster(BitMap->Planes[i],Width,Height);
2890 FreeVecPooled(Sizes);
2895 /* CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend):
2897 * Create a new bitmap with given properties.
2900 struct BitMap *
2901 CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend)
2903 if(Kick30)
2904 return(AllocBitMap(Width,Height,Depth,Flags,Friend));
2905 else
2907 struct BitMap *BitMap;
2908 LONG Plus;
2909 LONG *Sizes;
2911 if(Depth > 8)
2912 Plus = (Depth - 8) * sizeof(PLANEPTR);
2913 else
2914 Plus = 0;
2916 if(!(Sizes = (LONG *)AllocVecPooled(sizeof(LONG) * 2 + sizeof(struct BitMap) + Plus,MEMF_CLEAR)))
2917 BitMap = NULL;
2918 else
2920 LONG i;
2922 BitMap = (struct BitMap *)&Sizes[2];
2924 InitBitMap(BitMap,Depth,Width,Height);
2926 for(i = 0 ; i < BitMap->Depth ; i++)
2928 if(!(BitMap->Planes[i] = AllocRaster(Width,Height)))
2930 LONG j;
2932 for(j = 0 ; j < i ; j++)
2933 FreeRaster(BitMap->Planes[j],Width,Height);
2935 FreeVecPooled(Sizes);
2937 return(NULL);
2941 if(Flags & BMF_CLEAR)
2942 BltBitMap(BitMap,0,0,BitMap,0,0,Width,Height,0x00,(1 << Depth) - 1,NULL);
2944 Sizes[0] = Width;
2945 Sizes[1] = Height;
2948 return(BitMap);
2952 /* LaunchWorkCommon(LaunchMsg *Startup,BOOL Synchronous):
2954 * Does the final launch & cleanup work with the
2955 * startup packed provided.
2958 STATIC BOOL
2959 LaunchWorkCommon(LaunchMsg *Startup,BOOL Synchronous)
2961 /* Did we succeed in creating the startup message? */
2963 if(Startup)
2965 LONG Result;
2967 /* Launch the program. */
2969 Result = LaunchSomething(Config->MiscConfig->SuppressOutput ? (STRPTR)"NIL:" : Config->MiscConfig->WindowName,Synchronous,Startup);
2971 /* And return the result. */
2973 return((BOOL)(Result == 0));
2975 else
2976 return(FALSE);
2979 /* RexxLaunchCleanup(LaunchMsg *Startup):
2981 * Displays an error message for the ARexx script
2982 * to be launched.
2985 STATIC VOID
2986 LaunchRexxCleanup(LaunchMsg *Startup)
2988 if(Startup->Result != 0)
2989 Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Startup->Command,Startup->Result,Startup->Result2);
2992 /* LaunchRexxCommon(STRPTR Command):
2994 * Launch an ARexx command. This routine is always
2995 * asynchronous.
2998 BOOL
2999 LaunchRexxAsync(CONST_STRPTR Command)
3001 LaunchMsg *Startup;
3003 /* Skip leading blanks. */
3005 while(*Command == ' ' || *Command == '\t')
3006 Command++;
3008 /* Create the launch startup message. This will copy the
3009 * command string.
3012 Startup = CreateRexxCmdLaunchMsg(Command,NULL,LaunchRexxCleanup);
3014 /* Do the work. */
3016 return((BOOL)(LaunchWorkCommon(Startup,FALSE)));
3019 /* LaunchCommandCommon(STRPTR Command, BOOL Synchronous):
3021 * Launch a command, try to figure out if it's an ARexx
3022 * command, a plain batch file or a program and act
3023 * accordingly.
3026 STATIC BOOL
3027 LaunchCommandCommon(CONST_STRPTR OriginalCommand, BOOL Synchronous)
3029 STRPTR Command;
3030 UBYTE NameBuffer[MAX_FILENAME_LENGTH];
3031 BOOL IsScript;
3032 BPTR CommandFile;
3033 BPTR FileLock;
3034 LONG i;
3035 LaunchMsg *Startup;
3037 /* Chop off the arguments. */
3039 while(*OriginalCommand == ' ' || *OriginalCommand == '\t')
3040 OriginalCommand++;
3042 Command = (STRPTR)OriginalCommand;
3044 CopyMem(Command,NameBuffer,sizeof(NameBuffer) - 1);
3046 NameBuffer[sizeof(NameBuffer) - 1] = 0;
3048 for(i = 0 ; i < sizeof(NameBuffer) ; i++)
3050 if(NameBuffer[i] == ' ' || NameBuffer[i] == '\t')
3052 NameBuffer[i] = 0;
3053 break;
3057 /* Now do something useful. Check if the command
3058 * could be an ARexx script.
3061 if(CommandFile = Open(NameBuffer,MODE_OLDFILE))
3063 UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
3064 BOOL IsRexx = FALSE;
3065 LONG Len;
3067 /* 256 bytes may be not be enough, but then
3068 * we're only guessing.
3071 if((Len = Read(CommandFile,LocalBuffer,sizeof(LocalBuffer))) > 0)
3073 UBYTE c;
3075 for(i = 0 ; i < Len - 1 ; i++)
3077 c = LocalBuffer[i];
3079 /* Stop on invalid characters. */
3081 if((c < ' ' && c != '\r' && c != '\n' && c != '\a') || (c >= 127 && c < 160))
3082 break;
3083 else
3085 /* Looks like the typical
3086 * introductory comment line.
3089 if(c == '/' && LocalBuffer[i + 1] == '*')
3091 IsRexx = TRUE;
3092 break;
3098 Close(CommandFile);
3100 /* If it's a Rexx script, launch it. */
3102 if(IsRexx)
3103 return(LaunchRexxAsync(Command));
3106 /* Ok, second check. Does it have the script bit set? */
3108 IsScript = FALSE;
3110 if(FileLock = Lock(NameBuffer,ACCESS_READ))
3112 D_S(struct FileInfoBlock,FileInfo);
3114 if(Examine(FileLock,FileInfo))
3116 if(FileInfo->fib_Protection & FIBF_SCRIPT)
3117 IsScript = TRUE;
3120 UnLock(FileLock);
3123 /* If it's a script command, prepend the "Execute " command. */
3125 if(IsScript)
3127 /* Make room for the new command. */
3129 if(!(Command = AllocVecPooled(strlen("Execute ") + strlen(OriginalCommand) + 1,MEMF_ANY)))
3130 return(FALSE);
3131 else
3133 strcpy(Command,"Execute ");
3134 strcat(Command,OriginalCommand);
3138 /* Create the launch startup message. This will copy the
3139 * command string.
3142 Startup = CreateProgramLaunchMsg(Command,NULL);
3144 /* If we had to make a copy of the command name, release the memory. */
3146 if(Command != OriginalCommand)
3147 FreeVecPooled((APTR)Command);
3149 /* Do the work. */
3151 return((BOOL)(LaunchWorkCommon(Startup,Synchronous)));
3154 /* LaunchCommand(STRPTR Command):
3156 * Launches a command, synchronous version.
3159 BOOL
3160 LaunchCommand(CONST_STRPTR Command)
3162 return(LaunchCommandCommon(Command,TRUE));
3165 /* LaunchCommandAsync(STRPTR Command):
3167 * Launches a command, asynchronous version.
3170 BOOL
3171 LaunchCommandAsync(CONST_STRPTR Command)
3173 return(LaunchCommandCommon(Command,FALSE));
3176 /* LaunchProcess(STRPTR Name,VOID (*Entry)(VOID),BPTR Stream):
3178 * Launch a new process from given entry point, with given
3179 * name and I/O stream.
3182 struct Process *
3183 LaunchProcess(CONST_STRPTR Name,VOID (*Entry)(VOID),BPTR Stream)
3185 struct MsgPort *ConsoleTask;
3187 if(Stream && GoodStream(Stream))
3188 ConsoleTask = ((struct FileHandle *)BADDR(Stream))->fh_Type;
3189 else
3190 ConsoleTask = NULL;
3192 return(CreateNewProcTags(
3193 NP_Entry, Entry,
3194 NP_StackSize, 8000,
3195 NP_Name, Name,
3196 NP_Cli, TRUE,
3197 NP_ConsoleTask, ConsoleTask,
3199 ConsoleTask ? TAG_IGNORE : TAG_DONE,0,
3201 NP_Output, ConsoleTask ? BNULL : Stream,
3203 ConsoleTask ? NP_Input : TAG_IGNORE,Stream,
3204 TAG_DONE));
3207 /* String2Boolean(STRPTR String):
3209 * Compare string contents with table contents,
3210 * map the string to a boolean value.
3213 BOOL
3214 String2Boolean(CONST_STRPTR String)
3216 STATIC CONST_STRPTR TrueOptions[] =
3218 "ON",
3219 "TRUE",
3220 "T",
3221 "YES",
3222 "Y",
3226 LONG i;
3228 for(i = 0 ; i < NUM_ELEMENTS(TrueOptions) ; i++)
3230 if(!Stricmp(String,TrueOptions[i]))
3231 return(TRUE);
3234 return(FALSE);
3237 /* SendMessageGetReply(struct MsgPort *Port,struct Message *Message):
3239 * Send a message to a given MsgPort and wait for
3240 * the reply.
3243 VOID
3244 SendMessageGetReply(struct MsgPort *Port,struct Message *Message)
3246 struct MsgPort LocalPort;
3247 struct MsgPort *ReplyPort;
3249 ReplyPort = Message->mn_ReplyPort;
3251 InitSinglePort(&LocalPort);
3253 Message->mn_ReplyPort = &LocalPort;
3255 SetSignal(0,SIGF_SINGLE);
3257 PutMsg(Port,Message);
3258 WaitPort(&LocalPort);
3259 GetMsg(&LocalPort);
3261 Message->mn_ReplyPort = ReplyPort;
3264 /* SetOnlineState(BOOL IsOnline):
3266 * Set the current online state.
3269 VOID
3270 SetOnlineState(BOOL IsOnline)
3272 ObtainSemaphore(&OnlineSemaphore);
3274 WasOnline = Online;
3275 Online = IsOnline;
3277 if(WasOnline && !Online)
3278 ActivateJob(MainJobQueue,OnlineCleanupJob);
3280 ReleaseSemaphore(&OnlineSemaphore);
3283 /* SwapMem(APTR FromPtr,APTR ToPtr,LONG Size):
3285 * Exchange the contents of two memory regions.
3288 VOID
3289 SwapMem(APTR FromPtr,APTR ToPtr,LONG Size)
3291 UBYTE *From,*To,c;
3293 From = FromPtr;
3294 To = ToPtr;
3296 while(Size--)
3298 c = *From;
3299 *From++ = *To;
3300 *To++ = c;
3304 /* CloseIFFClip(struct IFFHandle *Handle):
3306 * Closes the clipboard opened by OpenIFFClip.
3309 BOOL
3310 CloseIFFClip(struct IFFHandle *Handle)
3312 if(Handle)
3314 CloseIFF(Handle);
3315 CloseClipboard((struct ClipboardHandle *)Handle->iff_Stream);
3316 FreeIFF(Handle);
3319 return(TRUE);
3322 /* OpenIFFClip(LONG Unit,LONG Mode):
3324 * Open the clipboard for reading or writing. This
3325 * routine handles all the initizalizations and
3326 * allocation and returns an IFFHandle ready
3327 * to be used.
3330 struct IFFHandle *
3331 OpenIFFClip(LONG Unit,LONG Mode)
3333 struct IFFHandle *Handle;
3334 LONG Error;
3336 if(Handle = AllocIFF())
3338 if(Handle->iff_Stream = (IPTR)OpenClipboard(Unit))
3340 InitIFFasClip(Handle);
3342 if(!(Error = OpenIFF(Handle,(Mode == MODE_NEWFILE) ? IFFF_WRITE : IFFF_READ)))
3343 return(Handle);
3345 CloseClipboard((struct ClipboardHandle *)Handle->iff_Stream);
3347 else
3348 Error = ERROR_NO_FREE_STORE;
3350 FreeIFF(Handle);
3352 else
3353 Error = ERROR_NO_FREE_STORE;
3355 SetIoErr(Error);
3357 return(FALSE);
3360 /* CloseIFFStream(struct IFFHandle *Handle):
3362 * Closes an IFF file opened by OpenIFFStream.
3365 BOOL
3366 CloseIFFStream(struct IFFHandle *Handle)
3368 if(Handle)
3370 BOOL Result;
3372 CloseIFF(Handle);
3373 Result = Close((BPTR)Handle->iff_Stream);
3374 FreeIFF(Handle);
3376 return(Result);
3378 else
3379 return(TRUE);
3382 /* OpenIFFStream(STRPTR Name,LONG Mode):
3384 * Open an IFF file for reading or writing. This
3385 * routine handles all the initizalizations and
3386 * allocation and returns an IFFHandle ready
3387 * to be used.
3390 struct IFFHandle *
3391 OpenIFFStream(STRPTR Name,LONG Mode)
3393 struct IFFHandle *Handle;
3394 LONG Error;
3396 if(Handle = AllocIFF())
3398 if(Handle->iff_Stream = (IPTR)Open(Name,Mode))
3400 InitIFFasDOS(Handle);
3402 if(!(Error = OpenIFF(Handle,(Mode == MODE_NEWFILE) ? IFFF_WRITE : IFFF_READ)))
3403 return(Handle);
3405 Close((BPTR)Handle->iff_Stream);
3407 if(Mode == MODE_NEWFILE)
3408 DeleteFile(Name);
3410 else
3411 Error = IoErr();
3413 FreeIFF(Handle);
3415 else
3416 Error = ERROR_NO_FREE_STORE;
3418 SetIoErr(Error);
3420 return(FALSE);
3423 /* InitHook(struct Hook *Hook,HOOKFUNC Func,APTR Data):
3425 * Set up a callback hook function.
3428 VOID
3429 InitHook(struct Hook *Hook,HOOKFUNC Func,APTR Data)
3431 #ifdef USE_GLUE
3432 Hook->h_Entry = HookEntry;
3433 Hook->h_SubEntry = Func;
3434 Hook->h_Data = Data;
3435 #else
3436 Hook->h_Entry = Func;
3437 Hook->h_Data = Data;
3438 #endif /* USE_GLUE */
3441 /* FitText(struct RastPort *RPort,UWORD Width,STRPTR String,LONG Len):
3443 * Check how many character fit into Width pixels.
3446 ULONG
3447 FitText(struct RastPort *RPort,UWORD Width,STRPTR String,LONG Len)
3449 struct TextExtent Extent;
3451 if(Len == -1)
3452 Len = strlen(String);
3454 return(TextFit(RPort,String,Len,&Extent,NULL,1,Width,32767));
3457 /* DispatchRexxDialMsgList(BOOL Ok):
3459 * Dispatch all queued dial requests.
3462 VOID
3463 DispatchRexxDialMsgList(BOOL Ok)
3465 struct RexxMsg *DialMsg;
3466 LONG Result;
3468 if(Ok)
3469 Result = RC_OK;
3470 else
3471 Result = RC_WARN;
3473 while(DialMsg = (struct RexxMsg *)RemHead(&RexxDialMsgList))
3475 DialMsg->rm_Result1 = Result;
3476 DialMsg->rm_Result2 = 0;
3478 ReplyMsg((struct Message *)DialMsg);
3482 /* CancelZModem():
3484 * Send the zmodem cancel sequence.
3487 VOID
3488 CancelZModem()
3490 if(UsesZModem)
3491 DoSerialWrite(ZModemCancel,20);
3494 /* WaitForHandshake():
3496 * Clears the handshaking signal, then waits for it.
3497 * Must be called while in Forbid().
3500 VOID
3501 WaitForHandshake()
3503 SetSignal(0,SIG_HANDSHAKE);
3504 Wait(SIG_HANDSHAKE);
3507 /* ShakeHands(struct Task *Notify,ULONG NotifyMask):
3509 * Send a signal to a Task and wait for it to
3510 * reply with the handshake signal.
3513 VOID
3514 ShakeHands(struct Task *Notify,ULONG NotifyMask)
3516 if(Notify)
3518 Forbid();
3520 Signal(Notify,NotifyMask);
3522 WaitForHandshake();
3524 Permit();
3528 /* GetViewPortExtra(struct ViewPort *ViewPort):
3530 * Gets the extra information associated with a viewport.
3533 struct ViewPortExtra *
3534 GetViewPortExtra(struct ViewPort *ViewPort)
3536 struct TagItem Tags[2] = {
3537 { VTAG_VIEWPORTEXTRA_GET, (IPTR)NULL, },
3538 { TAG_DONE }
3541 if(!VideoControl(ViewPort->ColorMap,Tags))
3542 return((struct ViewPortExtra *)Tags[0].ti_Data);
3543 else
3544 return(NULL);
3547 /* OpenToAppend(STRPTR Name,BOOL *Created):
3549 * Open a plain AmigaDOS file to append data to it. If a new file
3550 * is created this routine will indicate this by setting the
3551 * boolean variable pointed to by "Created" to TRUE.
3554 BPTR
3555 OpenToAppend(CONST_STRPTR Name,BOOL *Created)
3557 BPTR FileHandle;
3558 BPTR FileLock;
3560 if(FileLock = Lock(Name,EXCLUSIVE_LOCK))
3562 if(!(FileHandle = OpenFromLock(FileLock)))
3564 UnLock(FileLock);
3566 FileHandle = Open(Name,MODE_READWRITE);
3569 if(FileHandle)
3571 if(Seek(FileHandle,0,OFFSET_END) == -1)
3573 LONG Error;
3575 Error = IoErr();
3577 Close(FileHandle);
3579 SetIoErr(Error);
3581 return(BNULL);
3585 if(Created)
3586 *Created = FALSE;
3588 else
3590 if(FileHandle = Open(Name,MODE_NEWFILE))
3592 if(Created)
3593 *Created = TRUE;
3597 return(FileHandle);
3600 /* PushStatus(WORD NewStatus):
3602 * Remember the current status and set the new one.
3605 VOID
3606 PushStatus(WORD NewStatus)
3608 ObtainSemaphore(&StatusSemaphore);
3610 if(StatusStackPointer < 10)
3611 StatusStack[StatusStackPointer++] = NewStatus;
3613 ReleaseSemaphore(&StatusSemaphore);
3616 /* PopStatus():
3618 * Return to the old status value.
3621 VOID
3622 PopStatus()
3624 ObtainSemaphore(&StatusSemaphore);
3626 if(StatusStackPointer > 0)
3627 StatusStackPointer--;
3629 ReleaseSemaphore(&StatusSemaphore);
3632 /* GetStatus():
3634 * Returns the current status.
3637 WORD
3638 GetStatus()
3640 WORD Status;
3642 SafeObtainSemaphoreShared(&StatusSemaphore);
3644 if(StatusStackPointer > 0)
3645 Status = StatusStack[StatusStackPointer - 1];
3646 else
3647 Status = STATUS_READY;
3649 ReleaseSemaphore(&StatusSemaphore);
3651 if(Status == STATUS_READY && Get_xOFF())
3652 Status = STATUS_HOLDING;
3654 return(Status);
3657 /* Clear_xOFF():
3659 * Clears the xOFF stop marker.
3662 VOID
3663 Clear_xOFF()
3665 ObtainSemaphore(&xONxOFF_Semaphore);
3667 xOFF_Enabled = FALSE;
3669 UpdateSerialJob();
3671 ReleaseSemaphore(&xONxOFF_Semaphore);
3674 /* Set_xOFF():
3676 * Sets the xOFF stop marker unless access to the
3677 * marker is forbidden.
3680 VOID
3681 Set_xOFF()
3683 ObtainSemaphore(&xONxOFF_Semaphore);
3685 if(xONxOFF_Lock == 0)
3686 xOFF_Enabled = TRUE;
3688 UpdateSerialJob();
3690 ReleaseSemaphore(&xONxOFF_Semaphore);
3693 /* Get_xOFF():
3695 * Queries the current state of the xOFF marker.
3698 BOOL
3699 Get_xOFF()
3701 BOOL Result;
3703 SafeObtainSemaphoreShared(&xONxOFF_Semaphore);
3705 Result = xOFF_Enabled;
3707 ReleaseSemaphore(&xONxOFF_Semaphore);
3709 return(Result);
3712 /* Lock_xOFF():
3714 * Locks the current xOFF marker state.
3717 VOID
3718 Lock_xOFF()
3720 ObtainSemaphore(&xONxOFF_Semaphore);
3722 xONxOFF_Lock++;
3724 ReleaseSemaphore(&xONxOFF_Semaphore);
3727 /* Unlock_xOFF():
3729 * Unlocks the current xOFF marker state.
3732 VOID
3733 Unlock_xOFF()
3735 ObtainSemaphore(&xONxOFF_Semaphore);
3737 if(xONxOFF_Lock > 0)
3738 xONxOFF_Lock--;
3740 ReleaseSemaphore(&xONxOFF_Semaphore);
3743 /* MoveListViewNode():
3745 * Move the node of a list view somewhere.
3748 VOID
3749 MoveListViewNode(LayoutHandle *Handle,struct List *List,LONG ListID,struct Node *Node,LONG *Offset,LONG How)
3751 LT_SetAttributes(Handle,ListID,
3752 GTLV_Labels, ~0,
3753 TAG_DONE);
3755 MoveNode(List,Node,How);
3757 *Offset = GetNodeOffset(Node,List);
3759 LT_SetAttributes(Handle,ListID,
3760 GTLV_Labels, List,
3761 LALV_Selected, *Offset,
3762 TAG_DONE);
3765 /* StartProcessWaitForHandshake():
3767 * Create a new process and wait for the handshake
3768 * signal.
3771 struct Process *
3772 StartProcessWaitForHandshake(STRPTR Name,TASKENTRY Entry,IPTR Tag1,...)
3774 #ifdef __AROS__
3775 AROS_SLOWSTACKTAGS_PRE_AS(Tag1, struct Process *)
3776 struct TagItem *Args = AROS_SLOWSTACKTAGS_ARG(Tag1);
3777 #else
3778 struct Process *retval;
3779 struct TagItem *Args = &Tag1;
3780 #endif
3782 Forbid();
3784 if(retval = CreateNewProcTags(
3785 NP_Name, Name,
3786 NP_Entry, Entry,
3787 TAG_MORE,Args))
3788 WaitForHandshake();
3790 Permit();
3792 #ifdef __AROS__
3793 AROS_SLOWSTACKTAGS_POST
3794 #else
3795 return(retval);
3796 #endif
3799 /* LocalGetCurrentDirName(STRPTR Buffer,LONG BufferSize):
3801 * Obtains the name of the "current" directory of the
3802 * calling process, regardless of the current directory
3803 * of the Shell environment the process may be running in.
3806 BOOL
3807 LocalGetCurrentDirName(STRPTR Buffer,LONG BufferSize)
3809 return((BOOL)NameFromLock(((struct Process *)FindTask(NULL))->pr_CurrentDir,Buffer,BufferSize));
3812 /* SafeObtainSemaphoreShared():
3814 * This is for backwards compatibility with Kickstart 2.04 and
3815 * avoids a deadlock when trying to get a shared lock on
3816 * a semaphore already held in exclusive mode by the same Task.
3819 VOID
3820 SafeObtainSemaphoreShared(struct SignalSemaphore *Semaphore)
3822 /* Do it right with Kickstart 3.x. */
3824 if(Kick30)
3825 ObtainSemaphoreShared(Semaphore);
3826 else
3828 /* Try to get the shared semaphore */
3830 if(!AttemptSemaphoreShared(Semaphore))
3832 /* Check if we can get the exclusive version */
3834 if(!AttemptSemaphore(Semaphore))
3836 /* Oh well, wait for the shared lock */
3838 ObtainSemaphoreShared(Semaphore);
3844 /* LocalCreateTask(STRPTR Name,BYTE Priority,TASKENTRY Entry,ULONG StackSize,LONG NumArgs,...):
3846 * Special version of CreateTask() that allows for arguments to be passed to
3847 * the Task to be created.
3850 struct Task *
3851 LocalCreateTask(STRPTR Name,LONG Priority,TASKENTRY Entry,ULONG StackSize,LONG NumArgs,...)
3853 /* A MemList with an additional MemEntry following it. */
3855 struct FatMemList
3857 struct MemList MemList;
3858 struct MemEntry MemEntry;
3860 struct MemList *LocalMemList,*MemList;
3861 struct MemEntry *MemEntry;
3862 struct FatMemList FatMemList;
3863 struct Task *Task;
3866 /* Limit the Task priority to legal values. */
3868 if(Priority < -128)
3869 Priority = -128;
3870 else
3872 if(Priority > 127)
3873 Priority = 127;
3876 /* Clear the result. */
3878 Task = NULL;
3880 /* Round the stack size to a multiple of four. */
3882 StackSize = (StackSize + 3) & ~3;
3883 #ifdef __AROS__
3884 if (StackSize < AROS_STACKSIZE) StackSize = AROS_STACKSIZE;
3885 #endif
3887 /* Reset the contents of the local memory allocation request. */
3889 memset(&FatMemList,0,sizeof(FatMemList));
3890 LocalMemList = &FatMemList.MemList;
3892 /* Set up the memory allocation request; we want room for
3893 * the Task structure and the requested stack size plus
3894 * any arguments to pass to the new Task.
3897 LocalMemList->ml_NumEntries = 2;
3898 MemEntry = &LocalMemList->ml_ME[0];
3899 MemEntry[0].me_Reqs = MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR;
3900 MemEntry[0].me_Length = sizeof(struct Task);
3901 MemEntry[1].me_Reqs = MEMF_ANY|MEMF_CLEAR;
3902 MemEntry[1].me_Length = StackSize + NumArgs * sizeof(LONG);
3904 /* Try the allocation. */
3906 #ifdef __AROS__
3907 if(MemList = NewAllocEntry(LocalMemList, NULL))
3908 #else
3909 if(MemList = AllocEntry(LocalMemList))
3910 #endif
3912 #ifndef __AROS__
3913 /* Check if the allocation did work. */
3915 if((IPTR)MemList & 0x80000000)
3917 /* Strip the failure bit. */
3919 MemList = (struct MemList *)((IPTR)MemList & ~0x80000000);
3921 else
3922 #endif
3924 /* So we got the memory for the Task. */
3926 Task = (struct Task *)MemList->ml_ME[0].me_Addr;
3928 /* Initialize the Task data structure. We will not
3929 * copy the name to a separate buffer, it is assumed
3930 * that the name pointer will remain valid for the
3931 * entire life time of this Task.
3934 Task->tc_Node.ln_Pri = Priority;
3935 Task->tc_Node.ln_Type = NT_TASK;
3936 Task->tc_Node.ln_Name = Name;
3938 Task->tc_SPLower = MemList->ml_ME[1].me_Addr;
3939 Task->tc_SPUpper = (APTR)((IPTR)Task->tc_SPLower + MemList->ml_ME[1].me_Length);
3940 Task->tc_SPReg = (APTR)((IPTR)Task->tc_SPUpper - NumArgs * sizeof(IPTR));
3942 /* Add the memory to be released when the Task exits. */
3944 NewList(&Task->tc_MemEntry);
3945 AddTail(&Task->tc_MemEntry,(struct Node *)MemList);
3947 /* If there are any arguments to pass to the Task,
3948 * copy them onto the stack.
3951 if(NumArgs > 0)
3953 va_list VarArgs;
3954 int i;
3955 IPTR *argptr = (IPTR *)Task->tc_SPReg;
3957 va_start(VarArgs,NumArgs);
3958 for (i = 0; i < NumArgs; i++) {
3959 *(argptr++) = va_arg(VarArgs, IPTR);
3961 va_end(VarArgs);
3964 /* Try to launch the Task... */
3965 #ifdef AROS_BUG_FIXED
3966 Task = AddTask(Task,(APTR)Entry,NULL);
3967 #else
3968 if (0 == NumArgs) {
3969 Printf("AROS-term: Launched task with name '%s'!\n",Name);
3970 Task = AddTask(Task,(APTR)Entry,NULL);
3971 } else {
3972 Printf("AROS-term: Supposed to launch task with name '%s', but cannot do it!\n",Name);
3973 Task = NULL;
3975 #endif
3978 /* Check if the Task could be launched and clean
3979 * up if it couldn't.
3982 if(Task == NULL && MemList != NULL)
3983 FreeEntry(MemList);
3986 return(Task);
3989 /* ChangeWindowPtr(APTR *Old,APTR New):
3991 * Change the pr_WindowPtr entry and return the old value.
3994 VOID
3995 ChangeWindowPtr(APTR *Old,APTR New)
3997 struct Process *CurrentProcess;
3999 CurrentProcess = (struct Process *)FindTask(NULL);
4001 *Old = CurrentProcess->pr_WindowPtr;
4003 CurrentProcess->pr_WindowPtr = New;
4006 /* RestoreWindowPtr(APTR Old):
4008 * Restore the pr_WindowPtr to whatever it was poiting to.
4011 VOID
4012 RestoreWindowPtr(APTR Old)
4014 ((struct Process *)FindTask(NULL))->pr_WindowPtr = Old;
4017 /* DisableDOSRequesters(APTR *WindowPtr):
4019 * Turn off the AmigaDOS requesters.
4022 VOID
4023 DisableDOSRequesters(APTR *WindowPtr)
4025 ChangeWindowPtr(WindowPtr,(APTR)-1);
4028 /* EnableDOSRequesters(APTR WindowPtr):
4030 * Turn the AmigaDOS requesters back on.
4033 VOID
4034 EnableDOSRequesters(APTR WindowPtr)
4036 RestoreWindowPtr(WindowPtr);
4039 /* SpeechSynthesizerAvailable():
4041 * Checks if the speech synthesizer is available for use.
4044 BOOL
4045 SpeechSynthesizerAvailable()
4047 struct Library *LocalTranslatorBase;
4048 BOOL SpeechAvailable;
4050 SpeechAvailable = FALSE;
4052 if(LocalTranslatorBase = OpenLibrary("translator.library",0))
4054 //FIXME: Deactivated to make it compile for AROS.
4055 #ifndef __AROS__
4056 struct narrator_rb NarratorRequest;
4058 memset(&NarratorRequest,0,sizeof(NarratorRequest));
4059 NarratorRequest.message.io_Message.mn_Length = sizeof(NarratorRequest);
4061 if(!OpenDevice("narrator.device",0,(struct IORequest *)&NarratorRequest,NULL))
4063 SpeechAvailable = TRUE;
4065 CloseDevice((struct IORequest *)&NarratorRequest);
4068 CloseLibrary(LocalTranslatorBase);
4069 #endif
4072 return(SpeechAvailable);
4075 /* CurrentTimeToStamp(struct DateStamp *Stamp):
4077 * A replacement for DateStamp().
4080 VOID
4081 CurrentTimeToStamp(struct DateStamp *Stamp)
4083 struct timeval Now;
4085 GetSysTime(&Now);
4087 Stamp->ds_Days = Now.tv_secs / (24 * 60 * 60);
4088 Stamp->ds_Minute = (Now.tv_secs % (24 * 60 * 60)) / 60;
4089 Stamp->ds_Tick = (Now.tv_secs % 60) * TICKS_PER_SECOND + (TICKS_PER_SECOND * Now.tv_micro) / MILLION;
4092 /* SmartOpenDiskFont(struct TextAttr *TextAttr):
4094 * Opens a disk-resident font. Does not require diskfont.library
4095 * to be open all the time while the program is running.
4098 struct TextFont *
4099 SmartOpenDiskFont(struct TextAttr *TextAttr)
4101 struct TextFont *Result;
4103 Result = NULL;
4105 if(DiskfontBase = OpenLibrary("diskfont.library",0))
4107 Result = OpenDiskFont(TextAttr);
4109 CloseLibrary(DiskfontBase);
4112 if(!Result)
4113 Result = OpenFont(TextAttr);
4115 return(Result);
4118 /* ArmLimit(ULONG SecondsToGo):
4120 * Arm the limit counter. We remember the time when the limit
4121 * will be exceeded.
4124 VOID
4125 ArmLimit(ULONG SecondsToGo)
4127 GetSysTime(&LimitTime);
4128 LimitTime.tv_secs += SecondsToGo;
4131 /* DisarmLimit():
4133 * Clear the limit counter.
4136 VOID
4137 DisarmLimit()
4139 memset(&LimitTime,0,sizeof(LimitTime));
4142 /* CheckLimit():
4144 * Check if the limit counter has been triggered.
4145 * If triggered, clear the limit counter.
4148 BOOL
4149 CheckLimit()
4151 BOOL Triggered;
4153 Triggered = FALSE;
4155 if(LimitTime.tv_secs > 0 || LimitTime.tv_micro > 0)
4157 struct timeval Now;
4159 GetSysTime(&Now);
4161 if(-CmpTime(&Now,&LimitTime) >= 0)
4162 Triggered = TRUE;
4165 if(Triggered)
4166 DisarmLimit();
4168 return(Triggered);