home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d8xx
/
d832
/
term.lha
/
Term
/
term-3.1-Source.lha
/
termAux.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-19
|
52KB
|
2,744 lines
/*
** termAux.c
**
** Miscellaneous support routines
**
** Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
** All Rights Reserved
*/
#include "termGlobal.h"
/* Block window nest count. */
STATIC WORD BlockNestCount;
/* This variable stores the current state of the
* dialing menu items.
*/
STATIC BYTE DialItemsAvailable = TRUE;
/* GetPubScreenName(struct Screen *Screen,STRPTR Name):
*
* Get the name of a public screen.
*/
BYTE __regargs
GetPubScreenName(struct Screen *Screen,STRPTR Name)
{
struct List *PubScreenList;
struct PubScreenNode *ScreenNode;
PubScreenList = LockPubScreenList();
for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
{
if(ScreenNode -> psn_Screen == Screen)
{
strcpy(Name,ScreenNode -> psn_Node . ln_Name);
UnlockPubScreenList();
return(TRUE);
}
}
UnlockPubScreenList();
return(FALSE);
}
/* InitSinglePort(struct MsgPort *Port):
*
* Initialize a plain MsgPort (as created on the stack) for
* usage. Don't try this at home, kids!
*/
VOID __regargs
InitSinglePort(struct MsgPort *Port)
{
memset(Port,0,sizeof(struct MsgPort));
Port -> mp_Flags = PA_SIGNAL;
Port -> mp_SigBit = SIGB_SINGLE;
Port -> mp_SigTask = SysBase -> ThisTask;
NewList(&Port -> mp_MsgList);
}
/* GoodStream(BPTR Stream):
*
* Check to see whether the current input file
* is an interactive stream.
*/
BYTE __regargs
GoodStream(BPTR Stream)
{
if(!Stream)
{
struct Process *ThisProcess = (struct Process *)SysBase -> ThisTask;
Stream = ThisProcess -> pr_CIS;
}
if(Stream)
{
struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
if(Handle -> fh_Type)
{
if(IsInteractive(Stream))
return(TRUE);
}
}
return(FALSE);
}
/* GetProgramIcon():
*
* Try to find the icon of the program.
*/
struct DiskObject *
GetProgramIcon()
{
struct DiskObject *Icon = NULL;
/* Run from Workbench? */
if(WBenchMsg)
{
/* Sanity check. */
if(WBenchMsg -> sm_ArgList)
{
/* Yet another sanity check. */
if(WBenchMsg -> sm_ArgList -> wa_Name)
{
/* Try to find the icon in the current directory. */
if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
if(!Icon)
{
BPTR NewLock;
/* Move to the directory the
* program was run from.
*/
if(NewLock = Lock("PROGDIR:",ACCESS_READ))
{
BPTR OldLock;
OldLock = CurrentDir(NewLock);
/* Try to fetch the icon, use the
* default name if necessary.
*/
if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
if(!Icon)
{
if(Icon = GetDiskObjectNew("term"))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
}
CurrentDir(OldLock);
UnLock(NewLock);
}
}
}
}
}
/* Still no success. */
if(!Icon)
{
/* Use the default names. */
if(Icon = GetDiskObjectNew("term"))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
if(!Icon)
{
if(Icon = GetDiskObjectNew("PROGDIR:term"))
{
if(Icon -> do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
}
}
return(Icon);
}
/* GetPenIndex(LONG Pen):
*
* Get the table index corresponding to an on-screen
* text rendering pen.
*/
LONG __regargs
GetPenIndex(LONG Pen)
{
LONG i;
for(i = 0 ; i < 16 ; i++)
{
if(MappedPens[0][i] == Pen)
return(i);
}
}
/* GetScreenWidth(struct Window *Window):
*
* Query the current screen width.
*/
LONG __regargs
GetScreenWidth(struct Window *Window)
{
if(Window)
{
if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
return(ScreenWidth);
else
return(Window -> Width - (Window -> BorderLeft + Window -> BorderRight));
}
else
return(ScreenWidth);
}
/* GetScreenHeight(struct Window *Window):
*
* Query the current screen height.
*/
LONG __regargs
GetScreenHeight(struct Window *Window)
{
if(Window)
{
if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
return(ScreenHeight);
else
return(Window -> Height - (Window -> BorderTop + Window -> BorderBottom));
}
else
return(ScreenHeight);
}
/* GetLeft(struct Screen *Screen):
*
* Get the screen left edge.
*/
STATIC LONG __regargs
GetLeft(struct Screen *Screen)
{
if(Screen -> LeftEdge >= 0)
return(0);
else
return(-Screen -> LeftEdge);
}
/* GetScreenLeft(struct Window *Window):
*
* Query the current screen left edge.
*/
LONG __regargs
GetScreenLeft(struct Window *Window)
{
if(Window)
{
if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
return(GetLeft(Window -> WScreen));
else
return(Window -> LeftEdge + Window -> BorderLeft);
}
else
return(GetLeft(DefaultPubScreen));
}
/* GetTop(struct Screen *Screen):
*
* Get the screen top edge.
*/
STATIC LONG __regargs
GetTop(struct Screen *Screen)
{
if(Screen -> TopEdge >= 0)
return(0);
else
return(-Screen -> TopEdge);
}
/* GetScreenTop(struct Window *Window):
*
* Query the current screen top edge.
*/
LONG __regargs
GetScreenTop(struct Window *Window)
{
if(Window)
{
if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
return(GetTop(Window -> WScreen));
else
return(Window -> TopEdge + Window -> BorderTop);
}
else
return(GetTop(DefaultPubScreen));
}
/* OldGetAPen(struct RastPort *RPort):
*
* Query the current primary rendering colour (old style).
*/
ULONG __regargs
OldGetAPen(struct RastPort *RPort)
{
return((ULONG)RPort -> FgPen);
}
/* OldGetBPen(struct RastPort *RPort):
*
* Query the current seconary rendering colour (old style).
*/
ULONG __regargs
OldGetBPen(struct RastPort *RPort)
{
return((ULONG)RPort -> BgPen);
}
/* OldGetDrMd(struct RastPort *RPort):
*
* Query the current drawing mode (old style).
*/
ULONG __regargs
OldGetDrMd(struct RastPort *RPort)
{
return((ULONG)RPort -> DrawMode);
}
/* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
*
* Set the rendering plane mask (old style).
*/
ULONG __regargs
OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
{
RPort -> Mask = Mask;
return((ULONG)1);
}
/* NewGetAPen(struct RastPort *RPort):
*
* Query the current primary rendering colour (new style).
*/
ULONG __regargs
NewGetAPen(struct RastPort *RPort)
{
return(GetAPen(RPort));
}
/* NewGetBPen(struct RastPort *RPort):
*
* Query the current seconary rendering colour (new style).
*/
ULONG __regargs
NewGetBPen(struct RastPort *RPort)
{
return(GetBPen(RPort));
}
/* NewGetDrMd(struct RastPort *RPort):
*
* Query the current drawing mode (new style).
*/
ULONG __regargs
NewGetDrMd(struct RastPort *RPort)
{
return(GetDrMd(RPort));
}
/* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
*
* Set the rendering plane mask (new style).
*/
ULONG __regargs
NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
{
return(SetWriteMask(RPort,Mask));
}
/* SetWait(struct Window *Window):
*
* Set the busy wait mouse pointer.
*/
VOID
SetWait(struct Window *Window)
{
if(IntuitionBase -> LibNode . lib_Version >= 39)
{
SetWindowPointer(Window,
WA_BusyPointer, TRUE,
WA_PointerDelay, TRUE,
TAG_DONE);
}
else
SetPointer(Window,Stopwatch,16,16,-6,0);
}
/* ClrWait(struct Window *Window):
*
* Remove the busy wait mouse pointer.
*/
VOID
ClrWait(struct Window *Window)
{
if(IntuitionBase -> LibNode . lib_Version >= 39)
SetWindowPointer(Window,TAG_DONE);
else
ClearPointer(Window);
}
/* GetModeName(ULONG Mode):
*
* Get the name of a display mode.
*/
STRPTR
GetModeName(ULONG Mode)
{
STATIC UBYTE Buffer[DISPLAYNAMELEN + 1];
struct NameInfo NameInfo;
if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
strcpy(Buffer,NameInfo . Name);
else
{
struct DimensionInfo DimensionInfo;
if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_NAME,Mode))
{
STRPTR MonitorName;
switch(Mode & MONITOR_ID_MASK)
{
case NTSC_MONITOR_ID:
MonitorName = "NTSC: ";
break;
case PAL_MONITOR_ID:
MonitorName = "PAL: ";
break;
case VGA_MONITOR_ID:
MonitorName = "VGA: ";
break;
case A2024_MONITOR_ID:
MonitorName = "A2024: ";
break;
default:
MonitorName = "";
break;
}
SPrintf(Buffer,"%s%ld × %ld",MonitorName,DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1);
}
else
strcpy(Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
}
return(Buffer);
}
/* ModeOkay(ULONG ID):
*
* Checks whether a display mode ID will do for deep
* screen bitmaps.
*/
BYTE __regargs
ModeOkay(ULONG ID)
{
struct DimensionInfo DimensionInfo;
if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
{
if(DimensionInfo . MaxDepth >= 4)
return(TRUE);
}
return(FALSE);
}
/* SetRedialMenu():
*
* Make the `redial' menu item available or make it
* unavailable.
*/
VOID
SetRedialMenu()
{
BYTE Mode;
if(DialList)
{
if(DialList -> lh_Head -> ln_Succ)
Mode = TRUE;
else
Mode = FALSE;
}
else
Mode = FALSE;
if(Mode && DialItemsAvailable)
OnItem(MEN_REDIAL);
else
OffItem(MEN_REDIAL);
}
/* SetDialMenu(BYTE Mode):
*
* Block or enable the dialing menu.
*/
VOID
SetDialMenu(BYTE Mode)
{
if(Window && Menu)
{
if(Mode)
{
if(DialList)
{
if(DialList -> lh_Head -> ln_Succ)
OnItem(MEN_REDIAL);
else
OffItem(MEN_REDIAL);
}
else
OffItem(MEN_REDIAL);
OnItem(MEN_DIAL_NUMBER);
}
else
{
OffItem(MEN_REDIAL);
OffItem(MEN_DIAL_NUMBER);
}
DialItemsAvailable = Mode;
}
}
/* SetTransferMenu(BYTE Mode):
*
* Block or enable the transfer menu.
*/
VOID
SetTransferMenu(BYTE Mode)
{
if(Window && Menu)
{
if(Mode)
{
ULONG i;
for(i = MEN_UPLOAD_ASCII ; i <= MEN_DOWNLOAD_BINARY ; i++)
OnItem(i);
OnItem(MEN_TRANSFER);
}
else
{
ULONG i;
for(i = MEN_UPLOAD_ASCII ; i <= MEN_DOWNLOAD_BINARY ; i++)
OffItem(i);
OffItem(MEN_TRANSFER);
}
}
}
/* SetRasterMenu(BYTE Mode):
*
* Block or enable the menu entries associated with
* functions to access the screen raster.
*/
VOID
SetRasterMenu(BYTE Mode)
{
if(Window && Menu)
{
if(Mode)
{
OnItem(MEN_SAVE_AS_TEXT);
OnItem(MEN_PRINT_SCREEN);
OnItem(MEN_COPY);
OnItem(MEN_CLEAR);
}
else
{
OffItem(MEN_SAVE_AS_TEXT);
OffItem(MEN_PRINT_SCREEN);
OffItem(MEN_COPY);
OffItem(MEN_CLEAR);
}
}
}
/* PickFont(struct Window *Window,STRPTR Name,WORD *Height,BYTE MonoSpaced):
*
* Pick a font using asl.library
*/
BYTE
PickFont(struct Window *Window,STRPTR Name,WORD *Height,BYTE MonoSpaced)
{
struct FontRequester *Requester;
BYTE Result = FALSE;
if(Requester = (struct FontRequester *)AllocAslRequestTags(ASL_FontRequest,
ASL_Window, Window,
MonoSpaced ? ASL_FuncFlags : TAG_IGNORE, FONF_FIXEDWIDTH,
TAG_DONE))
{
if(AslRequestTags(Requester,
ASL_FontName, Name,
ASL_FontHeight, *Height,
TAG_DONE))
{
strcpy(Name,Requester -> fo_Attr . ta_Name);
*Height = Requester -> fo_Attr . ta_YSize;
Result = TRUE;
}
FreeAslRequest(Requester);
}
return(Result);
}
/* ExtractString():
*
* Extracts a string from a list separated by `|' characters.
*/
STRPTR __regargs
ExtractString(STRPTR String,STRPTR Destination,BYTE ReturnEnd)
{
STRPTR OldString;
if(ReturnEnd)
OldString = NULL;
else
OldString = String;
while(*String)
{
if(*String == '|')
{
*Destination = 0;
String++;
if(*String)
return(String);
else
return(OldString);
}
else
*Destination++ = *String++;
}
*Destination = 0;
return(OldString);
}
/* GetListSize(struct List *List):
*
* Determine the number of entries in a list.
*/
LONG
GetListSize(struct List *List)
{
struct Node *Node = List -> lh_Head;
LONG i = 0;
while(Node -> ln_Succ)
{
i++;
Node = Node -> ln_Succ;
}
return(i);
}
/* GetListNode(LONG Offset,struct List *List):
*
* Return the n-th Node entry in a standard exec list.
*/
struct Node *
GetListNode(LONG Offset,struct List *List)
{
struct Node *Node;
LONG i;
Node = List -> lh_Head;
for(i = 0 ; i < Offset ; i++)
{
if(!Node -> ln_Succ -> ln_Succ)
return(NULL);
Node = Node -> ln_Succ;
}
return(Node);
}
/* LogAction(STRPTR String,...):
*
* Write an action to the default log file.
*/
VOID __stdargs
LogAction(STRPTR String,...)
{
if(Config -> CaptureConfig -> LogActions && Config -> CaptureConfig -> LogFileName[0])
{
UBYTE DummyBuffer[512];
BPTR File;
va_list VarArgs;
/* Build a valid string. */
va_start(VarArgs,String);
VSPrintf(DummyBuffer,String,VarArgs);
va_end(VarArgs);
/* Does the log file already exist? */
if(GetFileSize(Config -> CaptureConfig -> LogFileName))
{
/* It does, let's append the data. */
if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_READWRITE))
{
if(Seek(File,0,OFFSET_END) == -1)
{
Close(File);
File = NULL;
}
}
}
else
{
/* Create a new file. */
if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_NEWFILE))
FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
}
/* The file is open, build the date/time string and
* write the log action.
*/
if(File)
{
UBYTE TimeBuffer[20],DateBuffer[20];
struct DateTime DateTime;
/* Obtain current time. */
DateStamp(&DateTime . dat_Stamp);
/* Convert it to human readable form. */
DateTime . dat_Format = FORMAT_DOS;
DateTime . dat_Flags = 0;
DateTime . dat_StrDay = NULL;
DateTime . dat_StrDate = DateBuffer;
DateTime . dat_StrTime = TimeBuffer;
/* Conversion succeeded? */
if(DateToStr(&DateTime))
FPrintf(File,"%s %s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
/* Done! */
Close(File);
}
}
}
/* FlushMsg(struct Window *Window):
*
* Cancel all pending messages of a window.
*/
VOID
FlushMsg(struct Window *Window)
{
struct IntuiMessage *Massage;
while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
ReplyMsg(&Massage -> ExecMessage);
}
/* GetString(STRPTR Prompt,STRPTR Buffer):
*
* Get a string from the user, very much the same as xpr_gets,
* but also including the `Load File' gadget.
*/
BYTE
GetString(BYTE LoadGadget,BYTE Password,WORD MaxChars,STRPTR Prompt,STRPTR Buffer)
{
struct Gadget *GadgetList = NULL;
struct Gadget *GadgetArray[4];
struct Window *PanelWindow;
UBYTE DummyBuffer[MAX_FILENAME_LENGTH];
struct FileRequester *FileRequest;
BYTE Success = FALSE;
if(CreateAllGetsGadgets(LoadGadget,Password,MaxChars,Buffer,Prompt,GadgetArray,&GadgetList,VisualInfo,Window -> WScreen))
{
if(PanelWindow = OpenWindowTags(NULL,
WA_Left, GetScreenLeft(Window) + (GetScreenWidth(Window) - SZ_GetWindowWidth()) / 2,
WA_Top, GetScreenTop(Window) + (GetScreenHeight(Window) - SZ_GetWindowHeight()) / 2,
WA_Width, SZ_GetWindowWidth(),
WA_Height, SZ_GetWindowHeight(),
WA_Activate, TRUE,
WA_DragBar, TRUE,
WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE,
WA_RMBTrap, TRUE,
WA_CustomScreen,Window -> WScreen,
WA_IDCMP, IDCMP_GADGETDOWN | IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_VANILLAKEY | IDCMP_RAWKEY | BUTTONIDCMP | STRINGIDCMP,
WA_Title, LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),
TAG_DONE))
{
struct IntuiMessage *Massage;
ULONG IClass,Code;
struct Gadget *Gadget;
BYTE Terminated = FALSE;
PushWindow(PanelWindow);
AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
GT_RefreshWindow(PanelWindow,NULL);
ActiveGadget = NULL;
SetSignal(0,SIG_BREAK);
while(!Terminated)
{
if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
break;
while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
{
IClass = Massage -> Class;
Code = Massage -> Code;
Gadget = (struct Gadget *)Massage -> IAddress;
GT_ReplyIMsg(Massage);
if(IClass == IDCMP_VANILLAKEY)
KeySelect(GadgetArray,3,Code,PanelWindow,&Gadget,&IClass,&Code);
if(IClass == IDCMP_RAWKEY && Code == HELP_CODE)
DisplayBeep(PanelWindow -> WScreen);
if(IClass == IDCMP_GADGETDOWN)
{
if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
ActiveGadget = Gadget;
}
if(IClass == IDCMP_ACTIVEWINDOW && ActiveGadget)
ActivateGadget(ActiveGadget,PanelWindow,NULL);
if(IClass == IDCMP_CLOSEWINDOW)
Terminated = TRUE;
if(IClass == IDCMP_GADGETUP)
{
switch(Gadget -> GadgetID)
{
case 0:
strcpy(Buffer,SZ_GetString(GadgetArray[0]));
Success = TRUE;
Terminated = TRUE;
break;
case 1:
BlockWindow(PanelWindow);
if(FileRequest = GetFile(LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT)))
{
GT_SetGadgetAttrs(GadgetArray[0],PanelWindow,NULL,
GTST_String,DummyBuffer,
TAG_DONE);
FreeAslRequest(FileRequest);
}
ReleaseWindow(PanelWindow);
break;
case 2:
strcpy(Buffer,SZ_GetString(GadgetArray[0]));
Success = TRUE;
Terminated = TRUE;
break;
case 3:
Terminated = TRUE;
break;
}
}
}
}
ActiveGadget = NULL;
RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
PopWindow();
CloseWindow(PanelWindow);
}
}
FreeGadgets(GadgetList);
return(Success);
}
/* WakeUp(struct Window *Window):
*
* Pop a window to the front and alert the user.
*/
VOID __regargs
WakeUp(struct Window *Window)
{
if(Window)
{
if(Config -> TerminalConfig -> AlertMode == ALERT_SCREEN || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
{
if(Window -> WScreen -> LeftEdge > 0)
{
if(Window -> WScreen -> TopEdge > 0)
MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
else
MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,0);
}
else
{
if(Window -> WScreen -> TopEdge > 0)
MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
}
WindowToFront(Window);
ScreenToFront(Window -> WScreen);
}
}
if(Config -> TerminalConfig -> AlertMode == ALERT_BEEP || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
Beep();
}
/* AmigaDOSBackgroundServer(VOID):
*
* Background process to handle tool execution.
*/
STATIC VOID __saveds
AmigaDOSBackgroundServer(VOID)
{
struct Process *ThisProcess = (struct Process *)SysBase -> ThisTask;
struct Message *Message;
BPTR OldCOS,
NewCOS = NULL;
WaitPort(&ThisProcess -> pr_MsgPort);
Message = GetMsg(&ThisProcess -> pr_MsgPort);
/* Create console output stream, will be closed automagically on exit. */
if(!ThisProcess -> pr_COS && ThisProcess -> pr_ConsoleTask)
{
if(NewCOS = Open("*",MODE_NEWFILE))
{
OldCOS = ThisProcess -> pr_COS;
ThisProcess -> pr_COS = NewCOS;
}
}
SystemTags(Message -> mn_Node . ln_Name,TAG_DONE);
Forbid();
if(NewCOS)
{
ThisProcess -> pr_COS = OldCOS;
Close(NewCOS);
}
ReplyMsg(Message);
}
/* SendAmigaDOSCommand(STRPTR Name):
*
* Let the current default Shell execute an AmigaDOS
* command. Block until the command has returned.
*/
VOID
SendAmigaDOSCommand(STRPTR Name)
{
BPTR Stream;
/* Open the console window or whatever the user
* wants us to open here.
*/
if(Stream = Open(WindowName,MODE_NEWFILE))
{
struct MsgPort *ReplyPort;
if(ReplyPort = CreateMsgPort())
{
struct Message __aligned Message;
struct Process *NewProcess;
memset(&Message,0,sizeof(struct Message));
Message . mn_Node . ln_Name = Name;
Message . mn_Length = sizeof(struct Message);
Message . mn_ReplyPort = ReplyPort;
if(GoodStream(Stream))
{
struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
NewProcess = CreateNewProcTags(
NP_Entry, AmigaDOSBackgroundServer,
NP_Input, Stream,
NP_Output, NULL,
NP_ConsoleTask, Handle -> fh_Type,
NP_StackSize, 8000,
NP_Cli, TRUE,
NP_Name, "term AmigaDOS background process",
TAG_DONE);
}
else
{
NewProcess = CreateNewProcTags(
NP_Entry, AmigaDOSBackgroundServer,
NP_Output, Stream,
NP_ConsoleTask, NULL,
NP_StackSize, 8000,
NP_Cli, TRUE,
NP_Name, "term AmigaDOS background process",
TAG_DONE);
}
if(NewProcess)
{
ULONG SignalSet;
PutMsg(&NewProcess -> pr_MsgPort,&Message);
/* Go into loop and wait for the
* background process to return.
*/
FOREVER
{
SignalSet = Wait(SIG_REXX | PORTMASK(ReplyPort));
/* Yet another rexx message. */
if(SignalSet & SIG_REXX)
HandleRexx();
/* The background server has
* finished.
*/
if(SignalSet & PORTMASK(ReplyPort))
{
GetMsg(ReplyPort);
break;
}
}
}
else
Close(Stream);
DeleteMsgPort(ReplyPort);
}
else
Close(Stream);
}
BumpWindow(Window);
}
/* RexxBackgroundServer():
*
* The background process to handle the rexx
* massaging.
*/
#ifdef USE_AREXX
STATIC VOID __saveds
RexxBackgroundServer(VOID)
{
struct MsgPort *RexxPort;
struct Message *Message;
BPTR OldCOS,
NewCOS = NULL;
/* Look who we are. */
RexxBackgroundProcess = (struct Process *)SysBase -> ThisTask;
/* Wait for startup message. */
WaitPort(&RexxBackgroundProcess -> pr_MsgPort);
/* Pick the message up. */
Message = GetMsg(&RexxBackgroundProcess -> pr_MsgPort);
/* Create console output stream, will be closed automagically on exit. */
if(!RexxBackgroundProcess -> pr_COS && RexxBackgroundProcess -> pr_ConsoleTask)
{
if(NewCOS = Open("*",MODE_NEWFILE))
{
OldCOS = RexxBackgroundProcess -> pr_COS;
RexxBackgroundProcess -> pr_COS = NewCOS;
}
}
if(RexxPort = FindPort(RXSDIR))
{
struct MsgPort __aligned ReplyPort;
struct RexxMsg *RexxMsg;
InitSinglePort(&ReplyPort);
if(RexxMsg = CreateRexxMsg(&ReplyPort,"term",RexxPortName))
{
if(RexxMsg -> rm_Args[0] = CreateArgstring(Message -> mn_Node . ln_Name,strlen(Message -> mn_Node . ln_Name)))
{
RexxMsg -> rm_Action = RXCOMM;
Forbid();
SetSignal(0,SIGF_SINGLE);
PutMsg(RexxPort,(struct Message *)RexxMsg);
WaitPort(&ReplyPort);
GetMsg(&ReplyPort);
Permit();
/* This doesn't look too
* good, does it?
*/
if(RexxMsg -> rm_Result1)
Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Message -> mn_Node . ln_Name,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
DeleteArgstring(RexxMsg -> rm_Args[0]);
}
DeleteRexxMsg(RexxMsg);
}
}
/* We are done, lock and reply the message causing the
* main process to return to the input loop.
*/
Forbid();
if(NewCOS)
{
RexxBackgroundProcess -> pr_COS = OldCOS;
Close(NewCOS);
}
ReplyMsg(Message);
RexxBackgroundProcess = NULL;
}
/* SendARexxCommand(STRPTR Name):
*
* Let the ARexx server execute a command (or a script
* file if necessary) and block until the command
* has returned.
*/
VOID
SendARexxCommand(STRPTR Name)
{
struct MsgPort *ReplyPort;
/* Create a reply port for the info message. */
if(ReplyPort = CreateMsgPort())
{
struct Process *NewProcess;
struct Message __aligned Message;
BPTR Stream;
/* Set up the command name carrier message. */
memset(&Message,0,sizeof(struct Message));
Message . mn_Node . ln_Name = Name;
Message . mn_Length = sizeof(struct Message);
Message . mn_ReplyPort = ReplyPort;
/* Open the output file. */
if(WindowName[0])
Stream = Open(WindowName,MODE_NEWFILE);
else
Stream = NULL;
/* Create the background process which will
* handle all the messy rexx message sending
* for us.
*/
if(Stream)
{
if(GoodStream(Stream))
{
struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
NewProcess = (struct Process *)CreateNewProcTags(
NP_Entry, RexxBackgroundServer,
NP_Name, "term ARexx background process",
NP_Input, Stream,
NP_Output, NULL,
NP_Cli, TRUE,
NP_ConsoleTask, Handle -> fh_Type,
NP_StackSize, 16384,
TAG_END);
}
else
{
NewProcess = (struct Process *)CreateNewProcTags(
NP_Entry, RexxBackgroundServer,
NP_Name, "term ARexx background process",
NP_Output, Stream,
NP_Cli, TRUE,
NP_ConsoleTask, NULL,
NP_StackSize, 16384,
TAG_END);
}
}
else
{
NewProcess = (struct Process *)CreateNewProcTags(
NP_Entry, RexxBackgroundServer,
NP_Name, "term ARexx background process",
NP_Cli, TRUE,
NP_ConsoleTask, NULL,
NP_StackSize, 16384,
TAG_END);
}
/* Did we succeed in creating the process? */
if(NewProcess)
{
ULONG SignalSet;
/* Send the startup message. */
PutMsg(&NewProcess -> pr_MsgPort,&Message);
/* Go into loop and wait for the
* background process to return.
*/
FOREVER
{
SignalSet = Wait(SIG_REXX | PORTMASK(ReplyPort));
/* Yet another rexx message. */
if(SignalSet & SIG_REXX)
HandleRexx();
/* The background server has
* finished.
*/
if(SignalSet & PORTMASK(ReplyPort))
{
GetMsg(ReplyPort);
break;
}
}
}
else
{
if(Stream)
Close(Stream);
}
/* Delete the reply port. */
DeleteMsgPort(ReplyPort);
}
BumpWindow(Window);
}
#endif /* USE_AREXX */
/* BlockWindow(struct Window *Window):
*
* Block a window (show a wait mouse pointer, block
* windows, custom and system gadgets) by adding
* an invisible requester to it.
*/
VOID __regargs
BlockWindow(struct Window *Window)
{
if(Window)
{
struct Requester *InvisibleRequest = NULL;
WORD i;
Forbid();
/* Is this window already on the list? */
for(i = 0 ; i < 10 ; i++)
{
if(RequesterList[i] . RWindow == Window)
{
Permit();
return;
}
}
/* Look for an empty slot. */
for(i = 0 ; i < 10 ; i++)
{
if(!RequesterList[i] . RWindow)
{
InvisibleRequest = &RequesterList[i];
InvisibleRequest -> RWindow = (struct Window *)~0;
break;
}
}
Permit();
/* Install the wait mouse pointer. */
SetWait(Window);
/* Install the requester if possible. */
if(InvisibleRequest)
Request(InvisibleRequest,Window);
}
}
/* ReleaseWindow(struct Window *Window):
*
* Release a window blocked by `BlockWindow()'.
*/
VOID __regargs
ReleaseWindow(struct Window *Window)
{
if(Window)
{
struct Requester *InvisibleRequest = NULL;
WORD i;
/* Search all slots for the requester to block this window. */
for(i = 0 ; i < 10 ; i++)
{
if(RequesterList[i] . RWindow == Window)
{
InvisibleRequest = &RequesterList[i];
break;
}
}
/* Restore the mouse pointer. */
ClrWait(Window);
/* If disabled, restore the window. */
if(InvisibleRequest)
{
/* End the requester activity. */
EndRequest(InvisibleRequest,Window);
/* Reset it to zeroes. */
memset(InvisibleRequest,0,sizeof(struct Requester));
}
}
}
/* BlockWindows():
*
* Block the main window and the status window (i.e. disable
* the menu and attach a wait pointer).
*/
VOID
BlockWindows()
{
if(!(BlockNestCount++))
{
BlockWindow(Window);
BlockWindow(StatusWindow);
BlockWindow(PacketWindow);
BlockWindow(FastWindow);
BlockWindow(ReviewWindow);
BlockWindow(InfoWindow);
WeAreBlocking = TRUE;
}
}
/* ReleaseWindows():
*
* Reenable the menus and clear the wait pointer.
*/
VOID
ReleaseWindows()
{
if(!(--BlockNestCount))
{
ReleaseWindow(Window);
ReleaseWindow(StatusWindow);
ReleaseWindow(PacketWindow);
ReleaseWindow(FastWindow);
ReleaseWindow(ReviewWindow);
ReleaseWindow(InfoWindow);
WeAreBlocking = FALSE;
}
}
/* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
*
* Read a few bytes from a file (à la gets).
*/
LONG
LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
{
STATIC UBYTE Data[1024];
STATIC LONG ReadIndex = 0,
ReadLen = 0;
LONG BytesRead = 0,
i;
if(File)
{
for(i = 0 ; i < MaxChars ; i++)
{
if(ReadIndex >= ReadLen)
{
ReadLen = Read(File,Data,1024);
ReadIndex = 0;
if(ReadLen <= 0)
{
Buffer[i] = 0;
return(BytesRead);
}
}
BytesRead++;
if((Buffer[i] = Data[ReadIndex++]) == '\n')
{
Buffer[i + 1] = 0;
return(BytesRead);
}
}
return(BytesRead);
}
else
ReadIndex = ReadLen = 0;
}
/* GetBaudRate(STRPTR Buffer):
*
* Calculate the baud rate contained in a connect string.
*/
LONG
GetBaudRate(STRPTR Buffer)
{
LONG Rate,i,j;
for(i = j = 0 ; i < strlen(Buffer) ; i++)
{
if(Buffer[i] == ' ')
continue;
else
{
if(Buffer[i] >= '0' && Buffer[i] <= '9')
SharedBuffer[j++] = Buffer[i];
else
break;
}
}
SharedBuffer[j] = 0;
if(StrToLong(SharedBuffer,&Rate) > 0)
{
if(Rate > 0)
return(Rate);
}
return(0);
}
/* LookForIt(struct MenuItem *Item,ULONG ID):
*
* Auxilary routine for FindThisItem(), scans
* menu item and sub item lists.
*/
STATIC struct MenuItem * __inline
LookForIt(struct MenuItem *Item,ULONG ID)
{
while(Item)
{
if((ULONG)GTMENUITEM_USERDATA(Item) == ID)
return(Item);
else
{
if(Item -> SubItem)
{
register struct MenuItem *TheItem;
if(TheItem = LookForIt(Item -> SubItem,ID))
return(TheItem);
}
Item = Item -> NextItem;
}
}
return(NULL);
}
/* FindThisItem(struct Menu *FirstMenu,ULONG MenuID):
*
* Scan a menu for a menuitem associated with a
* menu ID.
*/
struct MenuItem *
FindThisItem(struct Menu *FirstMenu,ULONG MenuID)
{
struct MenuItem *Item;
while(FirstMenu)
{
if(Item = LookForIt(FirstMenu -> FirstItem,MenuID))
return(Item);
else
FirstMenu = FirstMenu -> NextMenu;
}
return(NULL);
}
/* GetItem(ULONG MenuID):
*
* Get the checkmark state of a menu item.
*/
BYTE __regargs
GetItem(ULONG MenuID)
{
if(Menu)
{
struct MenuItem *Item;
if(Item = FindThisItem(Menu,MenuID))
{
if(Item -> Flags & CHECKED)
return(TRUE);
}
}
return(FALSE);
}
/* SetItem(ULONG MenuID,BYTE Mode):
*
* Clear or set the checkmark or state of a menu item.
*/
VOID
SetItem(ULONG MenuID,BYTE Mode)
{
/* Is the global pull-down menu available? */
if(Menu)
{
struct MenuItem *Item;
/* Try to find the menu item and change
* the state of the checkmark.
*/
if(Item = FindThisItem(Menu,MenuID))
{
/* Remove the menu from the windows. */
if(Window)
ClearMenuStrip(Window);
if(StatusWindow)
ClearMenuStrip(StatusWindow);
if(FastWindow)
ClearMenuStrip(FastWindow);
if(InfoWindow)
ClearMenuStrip(InfoWindow);
switch(Mode)
{
case SETITEM_SETCHECK:
Item -> Flags |= CHECKED;
break;
case SETITEM_CLRCHECK:
Item -> Flags &= ~CHECKED;
break;
case SETITEM_ON:
Item -> Flags |= ITEMENABLED;
break;
case SETITEM_OFF:
Item -> Flags &= ~ITEMENABLED;
break;
}
/* Reattach the menu to the windows. */
if(Window)
ResetMenuStrip(Window,Menu);
if(StatusWindow)
ResetMenuStrip(StatusWindow,Menu);
if(FastWindow)
ResetMenuStrip(FastWindow,Menu);
if(InfoWindow)
ResetMenuStrip(InfoWindow,Menu);
}
}
}
/* GetFileSize(STRPTR Name):
*
* Simple routine to return the size of a file in
* bytes.
*/
LONG
GetFileSize(STRPTR Name)
{
struct FileInfoBlock *FileInfo;
LONG FileSize = 0;
if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
{
BPTR FileLock;
if(FileLock = Lock(Name,ACCESS_READ))
{
if(Examine(FileLock,FileInfo))
{
if(FileInfo -> fib_DirEntryType < 0)
FileSize = FileInfo -> fib_Size;
}
UnLock(FileLock);
}
FreeDosObject(DOS_FIB,FileInfo);
}
return(FileSize);
}
/* GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect):
*
* Call the asl.library file requester to select a single or
* a couple of files.
*/
struct FileRequester *
GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect,BYTE DirsOnly,STRPTR OKText)
{
struct FileRequester *AslFileRequest;
BYTE Result = FALSE,
DefaultPattern = FALSE;
LONG Flags,ExtFlags = 0;
WORD i,j;
STATIC UBYTE DirBuffer[MAX_FILENAME_LENGTH],
PatternBuffer[256],
OtherTitle[60];
/* We use this tag array to remember the size and
* position of the asl requester window.
*/
STATIC struct {
ULONG Tag1, LeftEdge;
ULONG Tag2, TopEdge;
ULONG Tag3, Width;
ULONG Tag4, Height;
ULONG Tag5;
} Dims = {
ASL_LeftEdge, -1,
ASL_TopEdge, -1,
ASL_Width, -1,
ASL_Height, -1,
TAG_DONE
};
for(i = j = 0 ; i < strlen(Title) ; i++)
{
if(Title[i] != '_')
OtherTitle[j++] = Title[i];
}
OtherTitle[j] = 0;
Title = OtherTitle;
if(DirsOnly)
{
ExtFlags |= FIL1F_NOFILES;
if(Pattern)
ExtFlags |= FIL1F_MATCHDIRS;
}
/* Empty directory string? Revert to the last directory
* name.
*/
if(!Directory[0])
{
if(!DirBuffer[0])
{
if(!GetCurrentDirName(DirBuffer,MAX_FILENAME_LENGTH))
DirBuffer[0] = 0;
}
Directory = DirBuffer;
}
/* If a wildcard pattern is required, add a gadget
* to display it.
*/
if(Pattern)
{
Flags = FILF_PATGAD;
if(!Pattern[0])
{
DefaultPattern = TRUE;
if(PatternBuffer[0])
Pattern = PatternBuffer;
else
Pattern = "#?";
}
else
{
if(!Stricmp(Pattern,"#?") || !Stricmp(Pattern,PatternBuffer))
{
DefaultPattern = TRUE;
Pattern = PatternBuffer;
}
}
}
else
{
Flags = 0;
Pattern = "#?";
}
/* Set the save flag if we are about to save something. */
if(SaveFlag)
Flags |= FILF_SAVE;
/* Set the multiselect bit if multiple files are
* to be selected (e.g. for batch file upload).
*/
if(MultiSelect)
Flags |= FILF_MULTISELECT;
/* Provide a standard `Ok' text if none
* specified.
*/
if(!OKText)
OKText = (SaveFlag ? LocaleString(MSG_GLOBAL_SAVE_TXT) : LocaleString(MSG_GLOBAL_OPEN_TXT));
/* Allocate the asl.library directory requester
* and display it.
*/
if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
ASL_Window, Window,
ASL_File, Name,
ASL_Dir, Directory,
Title ? ASL_Hail : TAG_IGNORE, Title,
ASL_FuncFlags, Flags | FILF_NEWIDCMP,
ASL_Pattern, Pattern,
ASL_OKText, OKText,
ASL_ExtFlags1, ExtFlags,
ASLFR_TextAttr, &UserFont,
(Dims . LeftEdge == -1) ? TAG_DONE : TAG_MORE,&Dims))
{
if(AslRequestTags(AslFileRequest,TAG_DONE))
{
Dims . LeftEdge = AslFileRequest -> rf_LeftEdge;
Dims . TopEdge = AslFileRequest -> rf_TopEdge;
Dims . Width = AslFileRequest -> rf_Width;
Dims . Height = AslFileRequest -> rf_Height;
if(!DirsOnly)
{
/* Do we have a valid file name? */
if(AslFileRequest -> rf_File[0])
{
/* Build a legal path/file string. */
strcpy(Buffer,AslFileRequest -> rf_Dir);
AddPart((STRPTR)Buffer,(STRPTR)AslFileRequest -> rf_File,MAX_FILENAME_LENGTH);
Result = TRUE;
strcpy(DirBuffer,AslFileRequest -> rf_Dir);
}
}
else
{
if(AslFileRequest -> rf_Dir[0])
{
strcpy(Buffer,AslFileRequest -> rf_Dir);
Result = TRUE;
strcpy(DirBuffer,AslFileRequest -> rf_Dir);
}
}
}
}
/* We didn't get a file, no need to keep the
* file requester.
*/
if(!Result && AslFileRequest)
{
FreeAslRequest(AslFileRequest);
return(NULL);
}
else
{
if(SaveFlag)
{
if(GetFileSize(Buffer))
{
if(!MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_OVERWRITE_TXT),LocaleString(MSG_GLOBAL_REPLACE_CANCEL_TXT),FilePart(Buffer)))
{
FreeAslRequest(AslFileRequest);
return(NULL);
}
}
}
if(DefaultPattern)
strcpy(PatternBuffer,AslFileRequest -> rf_Pat);
return(AslFileRequest);
}
}
/* MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
*
* Really quite simple varargs version of Intuition's
* EasyRequest requester.
*/
WORD __stdargs
MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
{
struct EasyStruct Easy;
WORD Result;
ULONG IDCMP = NULL;
va_list VarArgs;
/* Standard data. */
Easy . es_StructSize = sizeof(struct EasyStruct);
Easy . es_Flags = NULL;
Easy . es_Title = (STRPTR)LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
Easy . es_TextFormat = (STRPTR)Text;
Easy . es_GadgetFormat = (STRPTR)Gadgets;
/* Use the argument array to build the
* requester and display it.
*/
va_start(VarArgs,Gadgets);
Result = EasyRequestArgs(Window,&Easy,&IDCMP,VarArgs);
va_end(VarArgs);
return(Result);
}
/* SelectTime():
*
* Searches for the correct unit/pay conversion values.
*/
VOID
SelectTime(struct PhoneEntry *SomeEntry)
{
struct TimeDateNode *TimeDateNode;
struct DateStamp __aligned Date;
struct ClockData ClockData;
UBYTE Time;
BYTE FoundOne = FALSE;
LONG i,Last;
/* Obtain current time and date. */
DateStamp(&Date);
/* Convert into a more suitable form (note: seconds are
* required as an input value, ice is extra).
*/
Amiga2Date(Date . ds_Days * 86400 + Date . ds_Minute * 60 + Date . ds_Tick / TICKS_PER_SECOND,&ClockData);
/* Apparently, in the US of A the week starts with Sunday, we'll
* wrap the week around to let it start with Monday.
*/
if(ClockData . wday)
ClockData . wday--;
else
ClockData . wday = 6;
/* Change the month, too... */
ClockData . month--;
/* First step: search for current day. */
TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
/* Skip first entry. */
TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
/* First step: search for date settings. */
while(TimeDateNode -> VanillaNode . ln_Succ)
{
/* Does it match a specific date? */
if(TimeDateNode -> Header . Month == ClockData . month && TimeDateNode -> Header . Day == ClockData . mday)
{
FoundOne = TRUE;
break;
}
TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
}
/* Second step: search for week day settings. */
if(!FoundOne)
{
TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
/* Skip first entry. */
TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
while(TimeDateNode -> VanillaNode . ln_Succ)
{
/* Does it match a specific day? */
if(TimeDateNode -> Header . Month == -1 && (TimeDateNode -> Header . Day & (1 << ClockData . wday)))
{
FoundOne = TRUE;
break;
}
TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
}
}
/* Third step: use default settings. */
if(!FoundOne)
TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
/* Convert current time to packed format. */
Time = DT_GET_TIME(ClockData . hour,ClockData . min);
/* Start with a blank. */
Last = -1;
/* Look for fitting time. */
for(i = 0 ; i < TimeDateNode -> Table[0] . Count ; i++)
{
/* The time we are looking for must be >= the
* current time.
*/
if(TimeDateNode -> Table[i] . Time > Time)
{
if(i == 0)
break;
else
{
Last = i - 1;
break;
}
}
else
continue;
}
/* If none is found, take the last one in the list.
* Note that this requires the list to be sorted in
* ascending order.
*/
if(Last == -1)
Last = TimeDateNode -> Table[0] . Count - 1;
/* Fill in the remaining data. */
PayPerUnit[DT_FIRST_UNIT] = TimeDateNode -> Table[Last] . PayPerUnit[DT_FIRST_UNIT];
PayPerUnit[DT_NEXT_UNIT] = TimeDateNode -> Table[Last] . PayPerUnit[DT_NEXT_UNIT];
SecPerUnit[DT_FIRST_UNIT] = TimeDateNode -> Table[Last] . SecPerUnit[DT_FIRST_UNIT];
SecPerUnit[DT_NEXT_UNIT] = TimeDateNode -> Table[Last] . SecPerUnit[DT_NEXT_UNIT];
}
/* CloseWindowSafely(struct Window *Window):
*
* Close a window freeing all messages pending at
* its user port (taken from example source code
* published once upon a time in Amiga Mail).
*/
VOID
CloseWindowSafely(struct Window *Window)
{
struct IntuiMessage *IntuiMessage;
struct Node *Successor;
Forbid();
IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
{
if(IntuiMessage -> IDCMPWindow == Window)
{
Remove(IntuiMessage);
ReplyMsg((struct Message *)IntuiMessage);
}
IntuiMessage = (struct IntuiMessage *)Successor;
}
Window -> UserPort = NULL;
ModifyIDCMP(Window,NULL);
Permit();
CloseWindow(Window);
}
/* WaitTime(LONG Secs,LONG Micros):
*
* Wait a given period of time.
*/
VOID
WaitTime(LONG Secs,LONG Micros)
{
TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
TimeRequest -> tr_time . tv_secs = Secs;
TimeRequest -> tr_time . tv_micro = Micros;
DoIO(TimeRequest);
}
/* GetEnvDOS(STRPTR Name,STRPTR Buffer):
*
* Get the contents of a vanilla AmigaDOS environment
* variable.
*/
STRPTR
GetEnvDOS(STRPTR Name,STRPTR Buffer)
{
LONG Size;
BPTR File,SomeLock;
Buffer[0] = 0;
/* Is ENV: present? */
if(SomeLock = Lock("Env:",ACCESS_READ))
{
UBYTE SomeBuffer[MAX_FILENAME_LENGTH];
UnLock(SomeLock);
strcpy(SomeBuffer,"Env:");
strcat(SomeBuffer,Name);
/* Open the file. */
if(File = Open(SomeBuffer,MODE_OLDFILE))
{
/* Read the contents. */
Size = Read(File,Buffer,256);
Close(File);
if(Size > 0)
{
Buffer[Size] = 0;
return(Buffer);
}
}
}
return(NULL);
}
/* SetEnvDOS(STRPTR Name,STRPTR Value):
*
* Set the contents of a vanilla AmigaDOS environment
* variable.
*/
BYTE
SetEnvDOS(STRPTR Name,STRPTR Value)
{
UBYTE Buffer[MAX_FILENAME_LENGTH],*Destination;
LONG Length;
BPTR File,FileLock;
BYTE Success = FALSE;
WORD i;
for(i = 0 ; i < 2 ; i++)
{
if(i)
Destination = "EnvArc:";
else
Destination = "Env:";
/* Is ENV:/ENVARC: present? */
if(FileLock = Lock(Destination,ACCESS_READ))
{
UnLock(FileLock);
strcpy(Buffer,Destination);
strcat(Buffer,Name);
/* There already is a variable of that
* name in the environment storage
* directory.
*/
if(FileLock = Lock(Buffer,ACCESS_WRITE))
{
UnLock(FileLock);
/* Delete the variable. */
if(!DeleteFile(Buffer))
{
Success = FALSE;
continue;
}
}
/* Set the new variable. */
if(Length = strlen(Value))
{
if(File = Open(Buffer,MODE_NEWFILE))
{
if(Write(File,Value,Length) != Length)
{
Close(File);
DeleteFile(Buffer);
Success = FALSE;
}
else
{
Close(File);
SetProtection(Buffer,FIBF_EXECUTE);
Success = TRUE;
}
}
else
Success = FALSE;
}
else
Success = TRUE;
}
else
Success = FALSE;
}
return(Success);
}
/* BumpWindow(struct Window *SomeWindow):
*
* Bring a window to the front (and shift the screen
* back to its initial position).
*/
VOID
BumpWindow(struct Window *SomeWindow)
{
if(SomeWindow -> WScreen -> LeftEdge > 0)
{
if(SomeWindow -> WScreen -> TopEdge > 0)
MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
else
MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,0);
}
else
{
if(SomeWindow -> WScreen -> TopEdge > 0)
MoveScreen(SomeWindow -> WScreen,0,-SomeWindow -> WScreen -> TopEdge);
}
ScreenToFront(SomeWindow -> WScreen);
ActivateWindow(SomeWindow);
}
/* PushWindow(struct Window *Window):
*
* Push/PopWindow implement a single lifo window stack
* which always updates the window to activate when
* LSHIFT+RSHIFT+RETURN is pressed. This routine will
* push a window on the stack.
*/
VOID
PushWindow(struct Window *Window)
{
if(WindowStackPtr < 5)
{
WindowStack[WindowStackPtr++] = Window;
TopWindow = Window;
}
}
/* PopWindow():
*
* Remove topmost window from window stack.
*/
VOID
PopWindow()
{
if(WindowStackPtr > 0)
{
WindowStackPtr--;
if(WindowStackPtr)
TopWindow = WindowStack[WindowStackPtr - 1];
else
TopWindow = Window;
}
}
/* LoadMacros(STRPTR Name,struct MacroKeys *Keys):
*
* Load the keyboard macros from a file.
*/
BYTE
LoadMacros(STRPTR Name,struct MacroKeys *Keys)
{
struct IFFHandle *Handle;
BYTE Success = FALSE;
struct StoredProperty *Prop;
struct TermInfo *TermInfo;
if(Handle = AllocIFF())
{
if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
{
InitIFFasDOS(Handle);
if(!OpenIFF(Handle,IFFF_READ))
{
/* Collect version number ID if
* available.
*/
if(!PropChunks(Handle,VersionProps,1))
{
/* The following line tells iffparse to stop at the
* very beginning of a `Type' chunk contained in a
* `TERM' FORM chunk.
*/
if(!StopChunk(Handle,ID_TERM,ID_KEYS))
{
/* Parse the file... */
if(!ParseIFF(Handle,IFFPARSE_SCAN))
{
/* Did we get a version ID? */
if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
{
TermInfo = (struct TermInfo *)Prop -> sp_Data;
/* Is it the file format we are able
* to read?
*/
if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
{
/* Probably an older revision. */
if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
{
memset(Keys,0,sizeof(struct MacroKeys));
if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
Success = TRUE;
}
}
else
{
/* The file read pointer is positioned
* just in front of the first data
* to be read, so let's don't disappoint
* iffparse and read it.
*/
if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
Success = TRUE;
}
}
else
{
/* File was created by WriteIFFData previous
* to revision 1.4.
*/
memset(Keys,0,sizeof(struct MacroKeys));
if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
Success = TRUE;
}
}
}
}
CloseIFF(Handle);
}
Close(Handle -> iff_Stream);
}
FreeIFF(Handle);
}
return(Success);
}
/* WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
*
* Write data to an IFF file (via iffparse.library).
*/
BYTE
WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
{
struct IFFHandle *Handle;
BYTE Success = FALSE;
/* Allocate a handle. */
if(Handle = AllocIFF())
{
/* Open an output stream. */
if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
{
/* Tell iffparse that this is
* a DOS handle.
*/
InitIFFasDOS(Handle);
/* Open the handle for writing. */
if(!OpenIFF(Handle,IFFF_WRITE))
{
/* Push outmost chunk onto stack. */
if(!PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN))
{
/* Add a version identifier. */
if(!PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN))
{
struct TermInfo TermInfo;
TermInfo . Version = TermVersion;
TermInfo . Revision = TermRevision;
/* Write the version data. */
if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
{
/* Pop the version chunk, i.e. write it to the file. */
if(PopChunk(Handle))
Success = FALSE;
else
{
/* Push the real data chunk on the stack. */
if(!PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN))
{
/* Write the data. */
if(WriteChunkBytes(Handle,Data,Size) == Size)
Success = TRUE;
/* Pop the data chunk. */
if(PopChunk(Handle))
Success = FALSE;
}
else
Success = FALSE;
}
}
else
Success = FALSE;
}
/* Seems that we're done, now try to pop the FORM chunk
* and return.
*/
if(PopChunk(Handle))
Success = FALSE;
}
/* Close the handle (flush any pending data). */
CloseIFF(Handle);
}
/* Close the DOS handle itself. */
Close(Handle -> iff_Stream);
}
/* And free the IFF handle. */
FreeIFF(Handle);
}
if(Success)
SetProtection(Name,FIBF_EXECUTE);
return(Success);
}
/* ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
*
* Read data from a `TERM' FORM chunk contained in an IFF file.
*/
BYTE
ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
{
struct IFFHandle *Handle;
BYTE Success = FALSE;
struct StoredProperty *Prop;
struct TermInfo *TermInfo;
if(Handle = AllocIFF())
{
if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
{
InitIFFasDOS(Handle);
if(!OpenIFF(Handle,IFFF_READ))
{
/* Collect version number ID if
* available.
*/
if(!PropChunks(Handle,VersionProps,1))
{
/* The following line tells iffparse to stop at the
* very beginning of a `Type' chunk contained in a
* `TERM' FORM chunk.
*/
if(!StopChunk(Handle,ID_TERM,Type))
{
/* Parse the file... */
if(!ParseIFF(Handle,IFFPARSE_SCAN))
{
/* Did we get a version ID? */
if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
{
TermInfo = (struct TermInfo *)Prop -> sp_Data;
/* Is it the file format we are able
* to read?
*/
if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
Success = FALSE;
else
{
struct ContextNode *Chunk = CurrentChunk(Handle);
if(Chunk -> cn_Size < Size)
Size = Chunk -> cn_Size;
/* The file read pointer is positioned
* just in front of the first data
* to be read, so let's don't disappoint
* iffparse and read it.
*/
if(ReadChunkBytes(Handle,Data,Size) == Size)
Success = TRUE;
}
}
}
}
}
CloseIFF(Handle);
}
Close(Handle -> iff_Stream);
}
FreeIFF(Handle);
}
return(Success);
}