4 ** Miscellaneous support routines
6 ** Copyright © 1990-1996 by Olaf `Olsen' Barthel
17 # include <aros/asmcall.h>
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
));
28 /* Current timer state. */
30 STATIC BOOL TimerRunning
;
32 /* ListViewStateFill(struct LVDrawMsg *Msg):
34 * Draw the ghosting pattern over a ghosted listview line.
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.
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);
72 SetPens(RPort
,Pens
[BACKGROUNDPEN
],0,JAM1
);
74 RectFill(Window
->RPort
,Left
,Top
,Right
,Bottom
);
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.
87 GetListMaxPen(UWORD
*Pens
)
89 STATIC BYTE PenTable
[] =
101 for(i
= 0, Max
= -1 ; i
< NUM_ELEMENTS(PenTable
) ; i
++)
103 Pen
= Pens
[PenTable
[i
]];
112 /* FillBox(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height):
114 * Fill a rectangular area with the current foregroung colour.
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);
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.
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.
160 SetPens(struct RastPort
*RPort
,ULONG APen
,ULONG BPen
,ULONG DrMd
)
163 SetABPenDrMd(RPort
,APen
,BPen
,DrMd
);
166 if(APen
!= RPort
->FgPen
)
169 if(BPen
!= RPort
->BgPen
)
172 if(DrMd
!= RPort
->DrawMode
)
177 /* Atol(STRPTR Buffer):
179 * Convert ASCII representation to long word.
183 Atol(CONST_STRPTR Buffer
)
187 StrToLong(Buffer
,&Result
);
192 /* StripSpaces(STRPTR String):
194 * Strip leading and trailing spaces from a string.
198 StripSpaces(STRPTR String
)
207 while(*String
== ' ')
210 if(Len
= strlen(String
))
212 while(Len
> 0 && String
[Len
- 1] == ' ')
223 /* ReplaceWindowInfo(struct WindowInfo *NewInfo):
225 * Drop the window info into the right place.
229 ReplaceWindowInfo(struct WindowInfo
*NewInfo
)
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
));
245 ReleaseSemaphore(&WindowInfoSemaphore
);
250 * Store window size and position relative to
255 PutWindowInfo(LONG ID
,LONG Left
,LONG Top
,LONG Width
,LONG Height
)
257 LONG WindowLeft
,WindowTop
,WindowWidth
,WindowHeight
;
258 struct WindowInfo
*Info
= NULL
;
262 ObtainSemaphore(&WindowInfoSemaphore
);
264 for(i
= 0 ; WindowInfoTable
[i
].ID
!= -1 ; i
++)
266 if(WindowInfoTable
[i
].ID
== ID
)
268 Info
= &WindowInfoTable
[i
];
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
;
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
;
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
;
316 Info
->Height
= Height
;
318 ReleaseSemaphore(&WindowInfoSemaphore
);
323 * Set the window size and position in relation to
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
;
335 SafeObtainSemaphoreShared(&WindowInfoSemaphore
);
339 for(i
= 0 ; WindowInfoTable
[i
].ID
!= -1 ; i
++)
341 if(WindowInfoTable
[i
].ID
== ID
)
343 Info
= &WindowInfoTable
[i
];
349 if(Info
&& ID
== WINDOW_MAIN
)
353 *Width
= Info
->Width
;
354 *Height
= Info
->Height
;
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;
381 *Left
= WindowLeft
+ (WindowWidth
- *Width
) / 2;
385 if(DefWidth
&& !Info
->Width
)
388 *Left
= WindowLeft
+ (WindowWidth
- *Width
) / 2;
394 *Width
= Info
->Width
;
399 *Width
= WindowWidth
;
410 *Top
= WindowTop
+ (WindowHeight
- *Height
) / 2;
414 if(DefHeight
&& !Info
->Height
)
417 *Top
= WindowTop
+ (WindowHeight
- *Height
) / 2;
423 *Height
= Info
->Height
;
428 *Height
= WindowHeight
;
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
)
443 if(Info
->WindowFlags
& WC_ALIGNTOP
)
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
;
469 ReleaseSemaphore(&WindowInfoSemaphore
);
472 /* GetBitMapDepth(struct BitMap *BitMap):
474 * Return the depth of a BitMap.
478 GetBitMapDepth(struct BitMap
*BitMap
)
483 Depth
= (LONG
)GetBitMapAttr(BitMap
,BMA_DEPTH
);
485 Depth
= BitMap
->Depth
;
493 /* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
495 * Get screen DPI resolution values.
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.
521 AddProtection(STRPTR Name
,ULONG Mask
)
524 D_S(struct FileInfoBlock
,FileInfo
);
526 if(FileLock
= Lock(Name
,ACCESS_READ
))
528 if(Examine(FileLock
,FileInfo
))
532 if(Mask
== FIBF_EXECUTE
)
533 Mask
|= FileInfo
->fib_Protection
& ~(FIBF_OTR_EXECUTE
|FIBF_GRP_EXECUTE
);
535 Mask
|= FileInfo
->fib_Protection
;
537 SetProtection(Name
,Mask
);
544 /* GetPubScreenName(struct Screen *Screen,STRPTR Name):
546 * Get the name of a public screen.
550 GetPubScreenName(struct Screen
*Screen
,STRPTR Name
)
552 struct List
*PubScreenList
;
553 struct PubScreenNode
*ScreenNode
;
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
);
567 UnlockPubScreenList();
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!
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.
597 GoodStream(BPTR Stream
)
604 struct FileHandle
*Handle
= (struct FileHandle
*)BADDR(Stream
);
608 if(IsInteractive(Stream
))
618 * Try to find the icon of the program.
624 struct DiskObject
*Icon
= NULL
;
626 /* Run from Workbench? */
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
);
654 /* Move to the directory the
655 * program was run from.
658 if(NewLock
= Lock("PROGDIR:",ACCESS_READ
))
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
);
680 if(Icon
= GetDiskObjectNew("term"))
682 if(Icon
->do_Type
!= WBTOOL
)
684 FreeDiskObject(Icon
);
700 /* Still no success. */
704 /* Use the default names. */
706 if(Icon
= GetDiskObjectNew("term"))
708 if(Icon
->do_Type
!= WBTOOL
)
710 FreeDiskObject(Icon
);
718 if(Icon
= GetDiskObjectNew("PROGDIR:term"))
720 if(Icon
->do_Type
!= WBTOOL
)
722 FreeDiskObject(Icon
);
733 /* GetPenIndex(LONG Pen):
735 * Get the table index corresponding to an on-screen
736 * text rendering pen.
740 GetPenIndex(LONG Pen
)
744 for(i
= 0 ; i
< 16 ; i
++)
746 if(MappedPens
[0][i
] == Pen
)
756 /* GetScreenWidth(struct Window *Window):
758 * Query the current screen width.
762 GetScreenWidth(struct Window
*Window
)
766 if(Window
->Width
> ScreenWidth
|| Window
->LeftEdge
< -Window
->WScreen
->LeftEdge
|| Window
->LeftEdge
+ Window
->WScreen
->LeftEdge
+ Window
->Width
> ScreenWidth
)
769 return(Window
->Width
- (Window
->BorderLeft
+ Window
->BorderRight
));
775 /* GetScreenHeight(struct Window *Window):
777 * Query the current screen height.
781 GetScreenHeight(struct Window
*Window
)
785 if(Window
->Height
> ScreenHeight
|| Window
->TopEdge
< -Window
->WScreen
->TopEdge
|| Window
->TopEdge
+ Window
->WScreen
->TopEdge
+ Window
->Height
> ScreenHeight
)
786 return(ScreenHeight
);
788 return(Window
->Height
- (Window
->BorderTop
+ Window
->BorderBottom
));
791 return(ScreenHeight
);
794 /* GetLeft(struct Screen *Screen):
796 * Get the screen left edge.
800 GetLeft(struct Screen
*Screen
)
802 if(Screen
->LeftEdge
>= 0)
805 return(-Screen
->LeftEdge
);
808 /* GetScreenLeft(struct Window *Window):
810 * Query the current screen left edge.
814 GetScreenLeft(struct Window
*Window
)
818 if(Window
->Width
> ScreenWidth
|| Window
->LeftEdge
< -Window
->WScreen
->LeftEdge
|| Window
->LeftEdge
+ Window
->WScreen
->LeftEdge
+ Window
->Width
> ScreenWidth
)
819 return(GetLeft(Window
->WScreen
));
821 return(Window
->LeftEdge
+ Window
->BorderLeft
);
825 struct Screen
*PubScreen
= LockPubScreen(NULL
);
828 Result
= GetLeft(PubScreen
? PubScreen
: SharedScreen
);
830 UnlockPubScreen(NULL
,PubScreen
);
836 /* OldGetAPen(struct RastPort *RPort):
838 * Query the current primary rendering colour (old style).
842 OldGetAPen(struct RastPort
*RPort
)
844 return((ULONG
)RPort
->FgPen
);
847 /* OldGetBPen(struct RastPort *RPort):
849 * Query the current seconary rendering colour (old style).
853 OldGetBPen(struct RastPort
*RPort
)
855 return((ULONG
)RPort
->BgPen
);
858 /* OldGetDrMd(struct RastPort *RPort):
860 * Query the current drawing mode (old style).
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).
875 OldSetWrMsk(struct RastPort
*RPort
,ULONG Mask
)
883 /* OldGetWrMsk(struct RastPort *RPort):
885 * Get the rendering plane mask (old style).
889 OldGetWrMsk(struct RastPort
*RPort
)
894 /* NewGetAPen(struct RastPort *RPort):
896 * Query the current primary rendering colour (new style).
900 NewGetAPen(struct RastPort
*RPort
)
902 return(GetAPen(RPort
));
905 /* NewGetBPen(struct RastPort *RPort):
907 * Query the current seconary rendering colour (new style).
911 NewGetBPen(struct RastPort
*RPort
)
913 return(GetBPen(RPort
));
916 /* NewGetDrMd(struct RastPort *RPort):
918 * Query the current drawing mode (new style).
922 NewGetDrMd(struct RastPort
*RPort
)
924 return(GetDrMd(RPort
));
927 /* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
929 * Set the rendering plane mask (new style).
933 NewSetWrMsk(struct RastPort
*RPort
,ULONG Mask
)
936 return(SetWriteMask(RPort
,Mask
));
941 /* NewGetWrMsk(struct RastPort *RPort):
943 * Get the rendering plane mask (new style).
947 NewGetWrMsk(struct RastPort
*RPort
)
954 RPTAG_WriteMask
,&Mask
,
960 /* SetWait(struct Window *Window):
962 * Set the busy wait mouse pointer.
966 SetWait(struct Window
*Window
)
969 LT_LockWindow(Window
);
972 /* ClrWait(struct Window *Window):
974 * Remove the busy wait mouse pointer.
978 ClrWait(struct Window
*Window
)
981 LT_UnlockWindow(Window
);
984 /* GetModeName(ULONG Mode):
986 * Get the name of a display mode.
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
);
998 struct DimensionInfo DimensionInfo
;
1000 if(GetDisplayInfoData(NULL
,(APTR
)&DimensionInfo
,sizeof(struct DimensionInfo
),DTAG_DIMS
,Mode
))
1004 switch(Mode
& MONITOR_ID_MASK
)
1006 case NTSC_MONITOR_ID
:
1008 MonitorName
= "NTSC:";
1011 case PAL_MONITOR_ID
:
1013 MonitorName
= "PAL:";
1016 case VGA_MONITOR_ID
:
1018 MonitorName
= "VGA:";
1021 case A2024_MONITOR_ID
:
1023 MonitorName
= "A2024:";
1032 LimitedSPrintf(BufferSize
,Buffer
,"%s%ldx%ld",MonitorName
,DimensionInfo
.TxtOScan
.MaxX
- DimensionInfo
.TxtOScan
.MinX
+ 1,DimensionInfo
.TxtOScan
.MaxY
- DimensionInfo
.TxtOScan
.MinY
+ 1);
1035 LimitedStrcpy(BufferSize
,Buffer
,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT
));
1039 /* ModeOkay(ULONG ID):
1041 * Checks whether a display mode ID will do for deep
1048 struct DimensionInfo DimensionInfo
;
1050 if(GetDisplayInfoData(NULL
,(APTR
)&DimensionInfo
,sizeof(struct DimensionInfo
),DTAG_DIMS
,ID
))
1052 if(DimensionInfo
.MaxDepth
>= 4)
1061 * Extracts a string from a list separated by `|' characters.
1065 ExtractString(STRPTR String
,STRPTR Destination
,BOOL ReturnEnd
)
1088 *Destination
++ = *String
++;
1096 /* RemoveGetNext(struct Node *Node):
1098 * Remove a node from a list and return the `next'
1099 * node to take its place.
1103 RemoveGetNext(struct Node
*Node
)
1107 /* Does the node have a successor? */
1109 if(Node
->ln_Succ
->ln_Succ
)
1110 Next
= Node
->ln_Succ
;
1113 /* Does it have a predecessor? */
1115 if(Node
->ln_Pred
->ln_Pred
)
1116 Next
= Node
->ln_Pred
;
1121 /* Remove the old node. */
1125 /* And return the node to take its place. */
1130 /* GetListSize(struct List *List):
1132 * Determine the number of entries in a list.
1136 GetListSize(struct List
*List
)
1141 for(Node
= List
->lh_Head
, i
= 0 ; Node
->ln_Succ
; Node
= Node
->ln_Succ
, i
++);
1146 /* GetListNode(LONG Offset,struct List *List):
1148 * Return the n-th Node entry in a standard exec list.
1152 GetListNode(LONG Offset
,struct List
*List
)
1157 for(Node
= List
->lh_Head
, Index
= 0 ; Node
->ln_Succ
; Node
= Node
->ln_Succ
, Index
++)
1166 /* CreateNode(STRPTR Name):
1168 * Put a name string into a list node.
1172 CreateNode(STRPTR Name
)
1176 if(Node
= (struct Node
*)AllocVecPooled(sizeof(struct Node
) + strlen(Name
) + 1,MEMF_ANY
))
1177 strcpy(Node
->ln_Name
= (STRPTR
)(Node
+ 1),Name
);
1182 /* CreateNodeArgs(STRPTR Format,...):
1184 * Put a name string into a list node, varargs version.
1188 CreateNodeArgs(STRPTR Format
,...)
1190 UBYTE LocalBuffer
[256];
1194 va_start(VarArgs
,Format
);
1195 LimitedVSPrintf(sizeof(LocalBuffer
),LocalBuffer
,Format
,VarArgs
);
1198 if(Node
= (struct Node
*)AllocVecPooled(sizeof(struct Node
) + strlen(LocalBuffer
) + 1,MEMF_ANY
))
1199 strcpy(Node
->ln_Name
= (STRPTR
)(Node
+ 1),LocalBuffer
);
1204 /* FormatAppend(STRPTR String,STRPTR Format,...):
1206 * Appends a formatted string to another string.
1210 FormatAppend(STRPTR String
,STRPTR Format
,...)
1214 String
+= strlen(String
);
1216 va_start(VarArgs
,Format
);
1217 VSPrintf(String
,Format
,VarArgs
);
1221 /* FreeList(struct List *List):
1223 * Remove all nodes from the list
1224 * and free them on the way.
1228 FreeList(struct List
*List
)
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
1246 GetNodeOffset(struct Node
*ListNode
,struct List
*List
)
1248 if(ListNode
&& List
)
1253 for(Node
= List
->lh_Head
, Offset
= 0 ; Node
->ln_Succ
; Node
= Node
->ln_Succ
, Offset
++)
1255 if(Node
== ListNode
)
1263 /* MoveList(struct List *From,struct List *To):
1265 * Move the contents of a list to a different list.
1269 MoveList(struct List
*From
,struct List
*To
)
1273 while(Node
= RemHead(From
))
1279 * Create a small, empty list.
1287 if(List
= (struct List
*)AllocVecPooled(sizeof(struct MinList
),MEMF_ANY
))
1295 * Free the contents of a list and the list itself.
1299 DeleteList(struct List
*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.
1318 MoveNode(struct List
*List
,struct Node
*Node
,LONG How
)
1324 if(Node
!= List
->lh_Head
)
1335 if(Node
!= List
->lh_Head
)
1339 Other
= Node
->ln_Pred
->ln_Pred
;
1343 Insert(List
,Node
,Other
);
1350 if(Node
!= List
->lh_TailPred
)
1354 Other
= Node
->ln_Succ
;
1358 Insert(List
,Node
,Other
);
1365 if(Node
!= List
->lh_TailPred
)
1376 /* LogAction(STRPTR String,...):
1378 * Write an action to the default log file.
1382 LogAction(CONST_STRPTR String
,...)
1384 if(Config
->CaptureConfig
->LogActions
&& Config
->CaptureConfig
->LogFileName
[0])
1386 UBYTE DummyBuffer
[512];
1392 /* Build a valid string. */
1394 va_start(VarArgs
,String
);
1395 LimitedVSPrintf(sizeof(DummyBuffer
),DummyBuffer
,String
,VarArgs
);
1398 /* Open the log file. */
1400 if(File
= OpenToAppend(Config
->CaptureConfig
->LogFileName
,&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.
1412 UBYTE DateBuffer
[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
);
1438 /* GetString(STRPTR Prompt,STRPTR Buffer):
1440 * Get a string from the user, very much the same as xpr_gets.
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
;
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;
1464 strcpy(LocalBuffer
,Buffer
);
1467 Prompt
= LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT
);
1469 if(Handle
= LT_CreateHandleTags(Window
->WScreen
,
1470 LAHN_LocaleHook
, &LocaleHook
,
1473 struct Window
*PanelWindow
;
1476 LA_Type
, VERTICAL_KIND
,
1480 LA_Type
, VERTICAL_KIND
,
1481 LA_LabelText
, Prompt
,
1487 LA_Type
, PASSWORD_KIND
,
1488 LA_STRPTR
, LocalBuffer
,
1491 GTST_MaxChars
, MaxChars
,
1497 LA_Type
, STRING_KIND
,
1498 LA_STRPTR
, LocalBuffer
,
1501 LAST_Picker
, LoadGadget
,
1505 LT_EndGroup(Handle
);
1509 LA_Type
,VERTICAL_KIND
,
1514 LAXB_FullSize
, TRUE
,
1517 LT_EndGroup(Handle
);
1520 LT_New(Handle
,LA_Type
,HORIZONTAL_KIND
,
1521 LAGR_SameSize
, TRUE
,
1526 LA_Type
, BUTTON_KIND
,
1527 LA_LabelID
, MSG_TERMXPR_OKAY_GAD
,
1529 LABT_ReturnKey
, TRUE
,
1530 LABT_ExtraFat
, TRUE
,
1534 LA_Type
, BUTTON_KIND
,
1535 LA_LabelID
, MSG_GLOBAL_CANCEL_GAD
,
1538 LABT_ExtraFat
, TRUE
,
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
,
1553 WA_SimpleRefresh
, TRUE
,
1556 struct IntuiMessage
*Message
;
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
)
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
)
1589 LT_UpdateStrings(Handle
);
1591 strcpy(Buffer
,LocalBuffer
);
1593 Success
= Done
= TRUE
;
1595 LT_PressButton(Handle
,GAD_OK
);
1602 LT_UpdateStrings(Handle
);
1604 strcpy(Buffer
,LocalBuffer
);
1606 Success
= Done
= TRUE
;
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
,
1639 LT_DeleteHandle(Handle
);
1645 /* WakeUp(struct Window *Window,LONG Sound):
1647 * Pop a window to the front and alert the user.
1651 WakeUp(struct Window
*Window
,LONG Sound
)
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
);
1662 MoveScreen(Window
->WScreen
,-Window
->WScreen
->LeftEdge
,0);
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
)
1682 * Block the main window and the status window (i.e. disable
1683 * the menu and attach a wait pointer).
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
);
1704 /* ReleaseWindows():
1706 * Reenable the menus and clear the wait pointer.
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
);
1727 if(Window
->Flags
& WFLG_WINDOWACTIVE
)
1739 /* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
1741 * Read a few bytes from a file (à la gets).
1745 LineRead(BPTR File
,STRPTR Buffer
,LONG MaxChars
)
1747 STATIC UBYTE Data
[1024];
1748 STATIC LONG ReadIndex
,ReadLen
;
1756 for(i
= 0 ; i
< MaxChars
; i
++)
1758 if(ReadIndex
>= ReadLen
)
1760 ReadLen
= Read(File
,Data
,sizeof(Data
));
1773 if((Buffer
[i
] = Data
[ReadIndex
++]) == '\n')
1782 ReadIndex
= ReadLen
= 0;
1787 /* GetBaudRate(STRPTR Buffer):
1789 * Calculate the baud rate contained in a connect string.
1793 GetBaudRate(STRPTR Buffer
)
1795 UBYTE LocalBuffer
[40];
1798 for(i
= j
= 0 ; i
< strlen(Buffer
) ; i
++)
1800 if(Buffer
[i
] == ' ')
1804 if(Buffer
[i
] >= '0' && Buffer
[i
] <= '9')
1805 LocalBuffer
[j
++] = Buffer
[i
];
1813 if(StrToLong(LocalBuffer
,&Rate
) > 0)
1822 /* GetFileSize(STRPTR Name):
1824 * Simple routine to return the size of a file in
1829 GetFileSize(CONST_STRPTR Name
)
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
;
1849 /* PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height):
1851 * Put back the default values for the requesters to open.
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
))
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
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
);
1886 LONG Left
,Top
,Width
,Height
;
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;
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
;
1919 /* ShowRequest(struct Window *Window,CONST_STRPTR Text,STRPTR CONST_Gadgets,...):
1921 * Really quite simple varargs version of Intuition's
1922 * EasyRequest requester.
1926 ShowRequest(struct Window
*Window
,CONST_STRPTR Text
,CONST_STRPTR Gadgets
,...)
1928 struct EasyStruct Easy
;
1931 for(i
= GadgetCount
= 0 ; i
< strlen(Gadgets
) ; i
++)
1933 if(Gadgets
[i
] == '|')
1937 /* Standard data. */
1939 Easy
.es_StructSize
= sizeof(struct EasyStruct
);
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
);
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
));
1960 LT_UnlockWindow(Window
);
1966 struct Window
*ReqWindow
;
1969 LT_LockWindow(Window
);
1971 if(ReqWindow
= BuildEasyRequestArgs(Window
,&Easy
,IDCMP_RAWKEY
,AROS_SLOWSTACKFORMAT_ARG(Gadgets
)))
1978 WaitPort(ReqWindow
->UserPort
);
1982 Result
= SysReqHandler(ReqWindow
,&IDCMP
,FALSE
);
1984 if(!Result
|| (Result
== -2 && !(IDCMP
& IDCMP_RAWKEY
)))
1988 FreeSysRequest(ReqWindow
);
1992 LT_UnlockWindow(Window
);
1995 AROS_SLOWSTACKFORMAT_POST(Gadgets
);
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).
2008 CloseWindowSafely(struct Window
*Window
)
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
)
2021 ReplyMsg((struct Message
*)Node
);
2025 Window
->UserPort
= NULL
;
2028 ModifyIDCMP(Window
,0);
2032 LT_DeleteWindowLock(Window
);
2034 CloseWindow(Window
);
2037 /* DelayTime(LONG Secs,LONG Micros):
2039 * Delay for a given period of time.
2043 DelayTime(LONG Secs
,LONG Micros
)
2049 StartTime(Secs
,Micros
);
2057 * Wait for a pending time request to finish.
2065 TimerRunning
= FALSE
;
2067 WaitIO((struct IORequest
*)TimeRequest
);
2073 * Stop the running timer.
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.
2094 StartTime(LONG Secs
,LONG 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
2119 GetEnvDOS(STRPTR Name
,STRPTR Buffer
,LONG BufferSize
)
2121 if(GetVar(Name
,Buffer
,256,0) >= 0)
2131 /* SetEnvDOS(STRPTR Name,STRPTR Value):
2133 * Set the contents of a vanilla AmigaDOS environment
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.
2150 UBYTE LocalBuffer
[MAX_FILENAME_LENGTH
];
2151 BOOL Result
= FALSE
;
2153 strcpy(LocalBuffer
,"ENVARC:");
2155 if(AddPart(LocalBuffer
,FilePart(Name
),sizeof(LocalBuffer
)))
2159 if(!(FileHandle
= Open(LocalBuffer
,MODE_NEWFILE
)))
2163 LONG Length
= strlen(Value
);
2165 if(Write(FileHandle
,Value
,Length
) == Length
)
2179 /* BumpWindow(struct Window *SomeWindow):
2181 * Bring a window to the front (and shift the screen
2182 * back to its initial position).
2186 BumpWindow(struct Window
*SomeWindow
)
2190 if(SomeWindow
->WScreen
->LeftEdge
> 0)
2192 if(SomeWindow
->WScreen
->TopEdge
> 0)
2193 MoveScreen(SomeWindow
->WScreen
,-SomeWindow
->WScreen
->LeftEdge
,-SomeWindow
->WScreen
->TopEdge
);
2195 MoveScreen(SomeWindow
->WScreen
,-SomeWindow
->WScreen
->LeftEdge
,0);
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.
2218 PushWindow(struct Window
*Window
)
2220 if(WindowStackPtr
< 5)
2222 WindowStack
[WindowStackPtr
++] = Window
;
2230 * Remove topmost window from window stack.
2236 if(WindowStackPtr
> 0)
2241 TopWindow
= WindowStack
[WindowStackPtr
- 1];
2249 * Split a full file name into a file and a drawer name.
2253 SplitFileName(STRPTR FullName
,STRPTR
*FileName
,STRPTR DrawerName
)
2255 if(FilePart(FullName
) == FullName
)
2258 *FileName
= FullName
;
2264 strcpy(DrawerName
,FullName
);
2266 Dummy
= PathPart(DrawerName
);
2270 *FileName
= FilePart(FullName
);
2274 /* BackfillRoutine():
2276 * Window layer backfill routine.
2281 BackfillRoutine(REG(a0
) struct Hook
*UnusedHook
,REG(a2
) struct RastPort
*RPort
,REG(a1
) LayerMsg
*Bounds
)
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
))
2292 struct RastPort RastPort
;
2294 CopyMem(RPort
,&RastPort
,sizeof(struct RastPort
));
2295 RastPort
.Layer
= NULL
;
2299 SetAPen(RPort
,Pens
[BACKGROUNDPEN
]);
2300 SetDrMd(RPort
,JAM2
);
2302 RectFill(RPort
,Bounds
->Bounds
.MinX
,Bounds
->Bounds
.MinY
,Bounds
->Bounds
.MaxX
,Bounds
->Bounds
.MaxY
);
2315 FindChar(STRPTR Template
,LONG c
)
2329 GetNameSegment(struct NameSegment
*NameSegment
,UBYTE
*cp
,LONG i
)
2331 UBYTE
*xp
= NameSegment
[i
].String
;
2333 while (*cp
&& !FindChar("._+-,@~=",*cp
))
2338 NameSegment
[i
].Separator
= *cp
;
2343 if(NameSegment
[i
].String
[0] || NameSegment
[i
].Separator
)
2350 CopyNameSegment(struct NameSegment
*NameSegment
,UBYTE
*Destination
,LONG Zap
)
2352 UBYTE
*cp
= Destination
,*xp
;
2354 for(xp
= NameSegment
[0].String
; *xp
; )
2357 if(NameSegment
[0].Separator
)
2361 *cp
++ = NameSegment
[0].Separator
;
2363 for(i
= Zap
+ 1 ; ; i
++)
2365 for(xp
= NameSegment
[i
].String
; *xp
; )
2368 if(NameSegment
[i
].Separator
)
2369 *cp
++ = NameSegment
[i
].Separator
;
2372 if(!NameSegment
[i
].String
[0])
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.
2390 ShrinkName(UBYTE
*Source
,UBYTE
*Destination
,LONG MaxLength
,BOOL FixSuffix
)
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
++);
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;
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
)
2429 if(NameSegment
[0].Separator
)
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;
2445 NameSegment
[0].String
[MaxLength
- Total
] = 0;
2448 CopyNameSegment(NameSegment
,Destination
,Zap
);
2451 strcpy(Destination
,Source
);
2454 strcpy(Destination
,Source
);
2458 BOOL GotDot
= FALSE
;
2459 LONG Len
= strlen(Destination
),Dots
;
2461 for(i
= Dots
= 0 ; i
< Len
; i
++)
2463 if(Destination
[i
] == '.')
2470 strcat(Destination
,".___");
2472 Destination
[Len
- 4] = '.';
2475 for(i
= Len
- 1 ; i
>= 0 ; i
--)
2477 if(Destination
[i
] == '.')
2480 Destination
[i
] = '_';
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).
2500 BuildFontName(STRPTR Destination
,LONG DestinationSize
,STRPTR Name
,LONG Size
)
2502 UBYTE LocalBuffer
[MAX_FILENAME_LENGTH
];
2505 Name
= FilePart(Name
);
2508 if(Len
> 5 && !Stricmp(&Name
[Len
- 5],".font"))
2510 strcpy(LocalBuffer
,Name
);
2512 LocalBuffer
[Len
- 5] = 0;
2517 LimitedSPrintf(DestinationSize
,Destination
,"%s %ld",Name
,Size
);
2520 /* FixName(STRPTR Name):
2522 * Build a correct AmigaDOS filename.
2526 FixName(STRPTR Name
)
2528 LONG NameLen
= strlen(Name
),i
;
2530 /* Replace special characters. */
2532 for(i
= 0 ; i
< NameLen
; i
++)
2558 /* Truncate the name. */
2564 /* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
2566 * Display an error message, in human readable form if possible.
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
, },
2595 UBYTE LocalBuffer1
[FAULT_MAX
],LocalBuffer2
[FAULT_MAX
];
2596 CONST_STRPTR PrimaryError
,SecondaryError
;
2598 PrimaryError
= SecondaryError
= NULL
;
2604 for(i
= 0 ; LocalErrors
[i
][0] ; i
++)
2606 if(LocalErrors
[i
][0] == Primary
)
2608 PrimaryError
= LocaleString(LocalErrors
[i
][1]);
2616 if(Fault(Primary
,NULL
,LocalBuffer1
,sizeof(LocalBuffer1
)))
2617 PrimaryError
= LocalBuffer1
;
2625 for(i
= 0 ; LocalErrors
[i
][0] ; i
++)
2627 if(LocalErrors
[i
][0] == Secondary
)
2629 SecondaryError
= LocaleString(LocalErrors
[i
][1]);
2637 if(Fault(Secondary
,NULL
,LocalBuffer2
,sizeof(LocalBuffer2
)))
2638 SecondaryError
= LocalBuffer2
;
2645 ShowRequest(Window
,PrimaryError
,LocaleString(MSG_GLOBAL_CONTINUE_TXT
),String
,SecondaryError
);
2647 ShowRequest(Window
,PrimaryError
,LocaleString(MSG_GLOBAL_CONTINUE_TXT
),SecondaryError
);
2652 BuildModeList(LONG
*Index
,ULONG DisplayMode
,MODEFILTER ModeFilter
,APTR UserData
)
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
;
2675 if(!(*ModeFilter
)(SomeMode
,UserData
))
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
);
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
)
2724 Remove((struct Node
*)Node
);
2726 FreeVecPooled(Node
);
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
)
2755 /* IsAssign(STRPTR Name):
2757 * Does a name refer to an assignment?
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
;
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
))
2802 /* Unlock the list of assignments. */
2804 UnLockDosList(LDF_ASSIGNS
| LDF_READ
);
2807 /* Return the result. */
2812 /* LockInAssign(BPTR TheLock,STRPTR TheAssignment):
2814 * Check if a file lock is part of an assignment.
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
2831 /* Get the default filesystem task
2832 * in case we stumble upon NULL
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
)
2850 while(DevProc
&& (DevProc
->dvp_Flags
& DVPF_ASSIGN
) && !Result
);
2852 /* Reset the default filesystem task. */
2854 SetFileSysTask(FileSysTask
);
2856 /* Free device process data. */
2859 FreeDeviceProc(DevProc
);
2864 /* DeleteBitMap(struct BitMap *BitMap):
2866 * Delete a bitmap created by CreateBitMap().
2870 DeleteBitMap(struct BitMap
*BitMap
)
2880 LONG i
,*Sizes
,Width
,Height
;
2882 Sizes
= &((LONG
*)BitMap
)[-2];
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.
2901 CreateBitMap(ULONG Width
,ULONG Height
,ULONG Depth
,ULONG Flags
,struct BitMap
*Friend
)
2904 return(AllocBitMap(Width
,Height
,Depth
,Flags
,Friend
));
2907 struct BitMap
*BitMap
;
2912 Plus
= (Depth
- 8) * sizeof(PLANEPTR
);
2916 if(!(Sizes
= (LONG
*)AllocVecPooled(sizeof(LONG
) * 2 + sizeof(struct BitMap
) + Plus
,MEMF_CLEAR
)))
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
)))
2932 for(j
= 0 ; j
< i
; j
++)
2933 FreeRaster(BitMap
->Planes
[j
],Width
,Height
);
2935 FreeVecPooled(Sizes
);
2941 if(Flags
& BMF_CLEAR
)
2942 BltBitMap(BitMap
,0,0,BitMap
,0,0,Width
,Height
,0x00,(1 << Depth
) - 1,NULL
);
2952 /* LaunchWorkCommon(LaunchMsg *Startup,BOOL Synchronous):
2954 * Does the final launch & cleanup work with the
2955 * startup packed provided.
2959 LaunchWorkCommon(LaunchMsg
*Startup
,BOOL Synchronous
)
2961 /* Did we succeed in creating the startup message? */
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));
2979 /* RexxLaunchCleanup(LaunchMsg *Startup):
2981 * Displays an error message for the ARexx script
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
2999 LaunchRexxAsync(CONST_STRPTR Command
)
3003 /* Skip leading blanks. */
3005 while(*Command
== ' ' || *Command
== '\t')
3008 /* Create the launch startup message. This will copy the
3012 Startup
= CreateRexxCmdLaunchMsg(Command
,NULL
,LaunchRexxCleanup
);
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
3027 LaunchCommandCommon(CONST_STRPTR OriginalCommand
, BOOL Synchronous
)
3030 UBYTE NameBuffer
[MAX_FILENAME_LENGTH
];
3037 /* Chop off the arguments. */
3039 while(*OriginalCommand
== ' ' || *OriginalCommand
== '\t')
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')
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
;
3067 /* 256 bytes may be not be enough, but then
3068 * we're only guessing.
3071 if((Len
= Read(CommandFile
,LocalBuffer
,sizeof(LocalBuffer
))) > 0)
3075 for(i
= 0 ; i
< Len
- 1 ; i
++)
3079 /* Stop on invalid characters. */
3081 if((c
< ' ' && c
!= '\r' && c
!= '\n' && c
!= '\a') || (c
>= 127 && c
< 160))
3085 /* Looks like the typical
3086 * introductory comment line.
3089 if(c
== '/' && LocalBuffer
[i
+ 1] == '*')
3100 /* If it's a Rexx script, launch it. */
3103 return(LaunchRexxAsync(Command
));
3106 /* Ok, second check. Does it have the script bit set? */
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
)
3123 /* If it's a script command, prepend the "Execute " command. */
3127 /* Make room for the new command. */
3129 if(!(Command
= AllocVecPooled(strlen("Execute ") + strlen(OriginalCommand
) + 1,MEMF_ANY
)))
3133 strcpy(Command
,"Execute ");
3134 strcat(Command
,OriginalCommand
);
3138 /* Create the launch startup message. This will copy the
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
);
3151 return((BOOL
)(LaunchWorkCommon(Startup
,Synchronous
)));
3154 /* LaunchCommand(STRPTR Command):
3156 * Launches a command, synchronous version.
3160 LaunchCommand(CONST_STRPTR Command
)
3162 return(LaunchCommandCommon(Command
,TRUE
));
3165 /* LaunchCommandAsync(STRPTR Command):
3167 * Launches a command, asynchronous version.
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.
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
;
3192 return(CreateNewProcTags(
3197 NP_ConsoleTask
, ConsoleTask
,
3199 ConsoleTask
? TAG_IGNORE
: TAG_DONE
,0,
3201 NP_Output
, ConsoleTask
? BNULL
: Stream
,
3203 ConsoleTask
? NP_Input
: TAG_IGNORE
,Stream
,
3207 /* String2Boolean(STRPTR String):
3209 * Compare string contents with table contents,
3210 * map the string to a boolean value.
3214 String2Boolean(CONST_STRPTR String
)
3216 STATIC CONST_STRPTR TrueOptions
[] =
3228 for(i
= 0 ; i
< NUM_ELEMENTS(TrueOptions
) ; i
++)
3230 if(!Stricmp(String
,TrueOptions
[i
]))
3237 /* SendMessageGetReply(struct MsgPort *Port,struct Message *Message):
3239 * Send a message to a given MsgPort and wait for
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
);
3261 Message
->mn_ReplyPort
= ReplyPort
;
3264 /* SetOnlineState(BOOL IsOnline):
3266 * Set the current online state.
3270 SetOnlineState(BOOL IsOnline
)
3272 ObtainSemaphore(&OnlineSemaphore
);
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.
3289 SwapMem(APTR FromPtr
,APTR ToPtr
,LONG Size
)
3304 /* CloseIFFClip(struct IFFHandle *Handle):
3306 * Closes the clipboard opened by OpenIFFClip.
3310 CloseIFFClip(struct IFFHandle
*Handle
)
3315 CloseClipboard((struct ClipboardHandle
*)Handle
->iff_Stream
);
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
3331 OpenIFFClip(LONG Unit
,LONG Mode
)
3333 struct IFFHandle
*Handle
;
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
)))
3345 CloseClipboard((struct ClipboardHandle
*)Handle
->iff_Stream
);
3348 Error
= ERROR_NO_FREE_STORE
;
3353 Error
= ERROR_NO_FREE_STORE
;
3360 /* CloseIFFStream(struct IFFHandle *Handle):
3362 * Closes an IFF file opened by OpenIFFStream.
3366 CloseIFFStream(struct IFFHandle
*Handle
)
3373 Result
= Close((BPTR
)Handle
->iff_Stream
);
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
3391 OpenIFFStream(STRPTR Name
,LONG Mode
)
3393 struct IFFHandle
*Handle
;
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
)))
3405 Close((BPTR
)Handle
->iff_Stream
);
3407 if(Mode
== MODE_NEWFILE
)
3416 Error
= ERROR_NO_FREE_STORE
;
3423 /* InitHook(struct Hook *Hook,HOOKFUNC Func,APTR Data):
3425 * Set up a callback hook function.
3429 InitHook(struct Hook
*Hook
,HOOKFUNC Func
,APTR Data
)
3432 Hook
->h_Entry
= HookEntry
;
3433 Hook
->h_SubEntry
= Func
;
3434 Hook
->h_Data
= Data
;
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.
3447 FitText(struct RastPort
*RPort
,UWORD Width
,STRPTR String
,LONG Len
)
3449 struct TextExtent Extent
;
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.
3463 DispatchRexxDialMsgList(BOOL Ok
)
3465 struct RexxMsg
*DialMsg
;
3473 while(DialMsg
= (struct RexxMsg
*)RemHead(&RexxDialMsgList
))
3475 DialMsg
->rm_Result1
= Result
;
3476 DialMsg
->rm_Result2
= 0;
3478 ReplyMsg((struct Message
*)DialMsg
);
3484 * Send the zmodem cancel sequence.
3491 DoSerialWrite(ZModemCancel
,20);
3494 /* WaitForHandshake():
3496 * Clears the handshaking signal, then waits for it.
3497 * Must be called while in Forbid().
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.
3514 ShakeHands(struct Task
*Notify
,ULONG NotifyMask
)
3520 Signal(Notify
,NotifyMask
);
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
, },
3541 if(!VideoControl(ViewPort
->ColorMap
,Tags
))
3542 return((struct ViewPortExtra
*)Tags
[0].ti_Data
);
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.
3555 OpenToAppend(CONST_STRPTR Name
,BOOL
*Created
)
3560 if(FileLock
= Lock(Name
,EXCLUSIVE_LOCK
))
3562 if(!(FileHandle
= OpenFromLock(FileLock
)))
3566 FileHandle
= Open(Name
,MODE_READWRITE
);
3571 if(Seek(FileHandle
,0,OFFSET_END
) == -1)
3590 if(FileHandle
= Open(Name
,MODE_NEWFILE
))
3600 /* PushStatus(WORD NewStatus):
3602 * Remember the current status and set the new one.
3606 PushStatus(WORD NewStatus
)
3608 ObtainSemaphore(&StatusSemaphore
);
3610 if(StatusStackPointer
< 10)
3611 StatusStack
[StatusStackPointer
++] = NewStatus
;
3613 ReleaseSemaphore(&StatusSemaphore
);
3618 * Return to the old status value.
3624 ObtainSemaphore(&StatusSemaphore
);
3626 if(StatusStackPointer
> 0)
3627 StatusStackPointer
--;
3629 ReleaseSemaphore(&StatusSemaphore
);
3634 * Returns the current status.
3642 SafeObtainSemaphoreShared(&StatusSemaphore
);
3644 if(StatusStackPointer
> 0)
3645 Status
= StatusStack
[StatusStackPointer
- 1];
3647 Status
= STATUS_READY
;
3649 ReleaseSemaphore(&StatusSemaphore
);
3651 if(Status
== STATUS_READY
&& Get_xOFF())
3652 Status
= STATUS_HOLDING
;
3659 * Clears the xOFF stop marker.
3665 ObtainSemaphore(&xONxOFF_Semaphore
);
3667 xOFF_Enabled
= FALSE
;
3671 ReleaseSemaphore(&xONxOFF_Semaphore
);
3676 * Sets the xOFF stop marker unless access to the
3677 * marker is forbidden.
3683 ObtainSemaphore(&xONxOFF_Semaphore
);
3685 if(xONxOFF_Lock
== 0)
3686 xOFF_Enabled
= TRUE
;
3690 ReleaseSemaphore(&xONxOFF_Semaphore
);
3695 * Queries the current state of the xOFF marker.
3703 SafeObtainSemaphoreShared(&xONxOFF_Semaphore
);
3705 Result
= xOFF_Enabled
;
3707 ReleaseSemaphore(&xONxOFF_Semaphore
);
3714 * Locks the current xOFF marker state.
3720 ObtainSemaphore(&xONxOFF_Semaphore
);
3724 ReleaseSemaphore(&xONxOFF_Semaphore
);
3729 * Unlocks the current xOFF marker state.
3735 ObtainSemaphore(&xONxOFF_Semaphore
);
3737 if(xONxOFF_Lock
> 0)
3740 ReleaseSemaphore(&xONxOFF_Semaphore
);
3743 /* MoveListViewNode():
3745 * Move the node of a list view somewhere.
3749 MoveListViewNode(LayoutHandle
*Handle
,struct List
*List
,LONG ListID
,struct Node
*Node
,LONG
*Offset
,LONG How
)
3751 LT_SetAttributes(Handle
,ListID
,
3755 MoveNode(List
,Node
,How
);
3757 *Offset
= GetNodeOffset(Node
,List
);
3759 LT_SetAttributes(Handle
,ListID
,
3761 LALV_Selected
, *Offset
,
3765 /* StartProcessWaitForHandshake():
3767 * Create a new process and wait for the handshake
3772 StartProcessWaitForHandshake(STRPTR Name
,TASKENTRY Entry
,IPTR Tag1
,...)
3775 AROS_SLOWSTACKTAGS_PRE_AS(Tag1
, struct Process
*)
3776 struct TagItem
*Args
= AROS_SLOWSTACKTAGS_ARG(Tag1
);
3778 struct Process
*retval
;
3779 struct TagItem
*Args
= &Tag1
;
3784 if(retval
= CreateNewProcTags(
3793 AROS_SLOWSTACKTAGS_POST
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.
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.
3820 SafeObtainSemaphoreShared(struct SignalSemaphore
*Semaphore
)
3822 /* Do it right with Kickstart 3.x. */
3825 ObtainSemaphoreShared(Semaphore
);
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.
3851 LocalCreateTask(STRPTR Name
,LONG Priority
,TASKENTRY Entry
,ULONG StackSize
,LONG NumArgs
,...)
3853 /* A MemList with an additional MemEntry following it. */
3857 struct MemList MemList
;
3858 struct MemEntry MemEntry
;
3860 struct MemList
*LocalMemList
,*MemList
;
3861 struct MemEntry
*MemEntry
;
3862 struct FatMemList FatMemList
;
3866 /* Limit the Task priority to legal values. */
3876 /* Clear the result. */
3880 /* Round the stack size to a multiple of four. */
3882 StackSize
= (StackSize
+ 3) & ~3;
3884 if (StackSize
< AROS_STACKSIZE
) StackSize
= AROS_STACKSIZE
;
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. */
3907 if(MemList
= NewAllocEntry(LocalMemList
, NULL
))
3909 if(MemList
= AllocEntry(LocalMemList
))
3913 /* Check if the allocation did work. */
3915 if((IPTR
)MemList
& 0x80000000)
3917 /* Strip the failure bit. */
3919 MemList
= (struct MemList
*)((IPTR
)MemList
& ~0x80000000);
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.
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
);
3964 /* Try to launch the Task... */
3965 #ifdef AROS_BUG_FIXED
3966 Task
= AddTask(Task
,(APTR
)Entry
,NULL
);
3969 Printf("AROS-term: Launched task with name '%s'!\n",Name
);
3970 Task
= AddTask(Task
,(APTR
)Entry
,NULL
);
3972 Printf("AROS-term: Supposed to launch task with name '%s', but cannot do it!\n",Name
);
3978 /* Check if the Task could be launched and clean
3979 * up if it couldn't.
3982 if(Task
== NULL
&& MemList
!= NULL
)
3989 /* ChangeWindowPtr(APTR *Old,APTR New):
3991 * Change the pr_WindowPtr entry and return the old value.
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.
4012 RestoreWindowPtr(APTR Old
)
4014 ((struct Process
*)FindTask(NULL
))->pr_WindowPtr
= Old
;
4017 /* DisableDOSRequesters(APTR *WindowPtr):
4019 * Turn off the AmigaDOS requesters.
4023 DisableDOSRequesters(APTR
*WindowPtr
)
4025 ChangeWindowPtr(WindowPtr
,(APTR
)-1);
4028 /* EnableDOSRequesters(APTR WindowPtr):
4030 * Turn the AmigaDOS requesters back on.
4034 EnableDOSRequesters(APTR WindowPtr
)
4036 RestoreWindowPtr(WindowPtr
);
4039 /* SpeechSynthesizerAvailable():
4041 * Checks if the speech synthesizer is available for use.
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.
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
);
4072 return(SpeechAvailable
);
4075 /* CurrentTimeToStamp(struct DateStamp *Stamp):
4077 * A replacement for DateStamp().
4081 CurrentTimeToStamp(struct DateStamp
*Stamp
)
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.
4099 SmartOpenDiskFont(struct TextAttr
*TextAttr
)
4101 struct TextFont
*Result
;
4105 if(DiskfontBase
= OpenLibrary("diskfont.library",0))
4107 Result
= OpenDiskFont(TextAttr
);
4109 CloseLibrary(DiskfontBase
);
4113 Result
= OpenFont(TextAttr
);
4118 /* ArmLimit(ULONG SecondsToGo):
4120 * Arm the limit counter. We remember the time when the limit
4125 ArmLimit(ULONG SecondsToGo
)
4127 GetSysTime(&LimitTime
);
4128 LimitTime
.tv_secs
+= SecondsToGo
;
4133 * Clear the limit counter.
4139 memset(&LimitTime
,0,sizeof(LimitTime
));
4144 * Check if the limit counter has been triggered.
4145 * If triggered, clear the limit counter.
4155 if(LimitTime
.tv_secs
> 0 || LimitTime
.tv_micro
> 0)
4161 if(-CmpTime(&Now
,&LimitTime
) >= 0)