home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magazyn Amiga Shareware Floppies
/
ma15.dms
/
ma15.adf
/
Yak
/
Source
/
hotkey_types.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-17
|
14KB
|
672 lines
/*
* Commands relating to Yak hotkey types
* mws, 27 April 1993
*/
#include <exec/types.h>
#include <exec/libraries.h>
#include <exec/memory.h>
#include <devices/inputevent.h>
#include <dos/dos.h>
#include <dos/datetime.h>
#include <dos/dostags.h>
#include <graphics/displayinfo.h>
#include <libraries/commodities.h>
#include <libraries/reqtools.h>
#include <libraries/locale.h>
#include <intuition/intuitionbase.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/commodities.h>
#include <proto/intuition.h>
#include <proto/reqtools.h>
#include <proto/locale.h>
#include <string.h>
#include "hotkey_types.h"
#include "yak.h"
#include "localprotos.h"
UWORD num_hkeys;
/*
* Utility functions
*/
#define HOW_ZIP 0
#define HOW_SHRINK 1
#define HOW_ENLARGE 2
static void HandleWindowKey(int how);
static void __saveds __asm putcharfunc( register __a0 struct Hook *h,
register __a2 void *object,
register __a1 char c);
static struct InputEvent *FlipIEvents(struct InputEvent *);
static int AddToStream(char *str);
static struct Window * FindWBWindow(void);
static void __saveds DoPalette(void);
static int palette_count;
static LONG beginCommand(char *command);
/*
* HotKey Action function prototypes
*/
static void act_DosCommand(YakHotKey *yhk), act_CloseWindow(YakHotKey *yhk),
act_ZipWindow(YakHotKey *yhk), act_ShrinkWindow(YakHotKey *yhk),
act_ExpandWindow(YakHotKey *yhk), act_CycleWindows(YakHotKey *yhk),
act_OpenPalette(YakHotKey *yhk), act_ScreenToFront(YakHotKey *yhk),
act_ScreenToBack(YakHotKey *yhk), act_ActivateWorkbench(YakHotKey *yhk),
act_CentreScreen(YakHotKey *yhk), act_BlankDisplay(YakHotKey *yhk),
act_InsertText(YakHotKey *yhk), act_InsertDate(YakHotKey *yhk),
act_ShowInterface(YakHotKey *yhk);
#define EMPTY_MINLIST {NULL,NULL,NULL}
YakHotKeyType yhktypes[NUM_HOTKEY_TYPES] = {
{ EMPTY_MINLIST, act_DosCommand, 0, TAKES_ARGUMENT|HAS_OPTIONS },
{ EMPTY_MINLIST, act_CloseWindow, 0, 0L },
{ EMPTY_MINLIST, act_ZipWindow, 0, 0L },
{ EMPTY_MINLIST, act_ShrinkWindow, 0, 0L },
{ EMPTY_MINLIST, act_ExpandWindow, 0, 0L },
{ EMPTY_MINLIST, act_CycleWindows, 0, 0L },
{ EMPTY_MINLIST, act_OpenPalette, 0, HAS_OPTIONS },
{ EMPTY_MINLIST, act_ScreenToFront, 0, 0L },
{ EMPTY_MINLIST, act_ScreenToBack, 0, 0L },
{ EMPTY_MINLIST, act_ActivateWorkbench, 0, 0L },
{ EMPTY_MINLIST, act_CentreScreen, 0, 0L },
{ EMPTY_MINLIST, act_BlankDisplay, 0, 0L },
{ EMPTY_MINLIST, act_InsertText, 0, TAKES_ARGUMENT },
{ EMPTY_MINLIST, act_InsertDate, 0, TAKES_ARGUMENT },
{ EMPTY_MINLIST, act_ShowInterface, 0, 0L }
};
/*
* Utility functions
*/
#define AdjustedLeftEdge(w, width) \
(w->LeftEdge + width > w->WScreen->Width ? \
w->WScreen->Width - width : w->LeftEdge)
#define AdjustedTopEdge(w, height) \
(w->TopEdge + height > w->WScreen->Height ? \
w->WScreen->Height - height : w->TopEdge)
/* zip/enlarge or whatever the currently active window */
static void
HandleWindowKey(int how)
{
struct Window *window;
ULONG lock;
lock = LockIBase(0);
if (window = IntuitionBase->ActiveWindow)
{
switch (how)
{
case HOW_ZIP:
if (window->Flags & WFLG_HASZOOM)
ZipWindow(window);
break;
case HOW_SHRINK:
if (window->Flags & WFLG_SIZEGADGET)
ChangeWindowBox(window,
window->LeftEdge,
window->TopEdge,
window->MinWidth,
window->MinHeight);
break;
case HOW_ENLARGE:
{ /* sometimes Max vars are -1 == NO LIMIT */
USHORT width, height;
width = window->MaxWidth;
if (width == -1) width = window->WScreen->Width-width;
height = window->MaxHeight;
if (height == -1) height = window->WScreen->Height-height;
if (window->Flags & WFLG_SIZEGADGET)
ChangeWindowBox(window,
AdjustedLeftEdge(window, width),
AdjustedTopEdge(window, height),
width,
height);
}
break;
} /* switch */
}
UnlockIBase(lock);
}
/* hook-function for inserting chars into input-stream */
static void __saveds __asm
putcharfunc( register __a0 struct Hook *h,
register __a2 void *object,
register __a1 char c)
{
struct InputEvent ev;
if (c) /* stop at null-terminator */
{
ev.ie_NextEvent = NULL;
InvertKeyMap(c, &ev, NULL);
AddIEvents(&ev);
}
}
/* and its associated structure */
static struct Hook putcharhook = {
{NULL, NULL},
(APTR)putcharfunc,
NULL,
NULL
};
/* given a list of input events, reverse their order */
/* NB: the list BETTER terminate... */
static struct InputEvent *
FlipIEvents(struct InputEvent *ie)
{
struct InputEvent *oldtail, *newtail = NULL;
while (ie)
{
/* remove head, set next event */
oldtail = ie->ie_NextEvent; /* this will be prev event */
ie->ie_NextEvent = newtail; /* add to head */
newtail = ie;
ie = oldtail; /* what's left */
}
return newtail;
}
/* adds a string to the input-stream */
static int
AddToStream(char *str)
{
struct InputEvent *ie;
if (ie = InvertString(str, NULL))
{
ie = FlipIEvents(ie);
AddIEvents(ie);
FreeIEvents(ie);
return TRUE;
}
return FALSE;
}
/* find (a) Workbench window */
static struct Window *
FindWBWindow()
{
struct Screen *s = LockPubScreen("Workbench");
if (s)
{
struct Window *w = s->FirstWindow;
WBenchToFront();
Forbid();
for (; w; w = w->NextWindow)
if (w->Flags & WFLG_WBENCHWINDOW)
break;
Permit();
UnlockPubScreen(NULL, s);
return w;
}
return NULL;
}
/* bring a palette up on frontmost screen */
/* CreateNewProc this function... */
static void __saveds
DoPalette()
{
struct ReqToolsBase *ReqToolsBase;
LONG tags[3];
palette_count++;
if (ReqToolsBase = (void *)OpenLibrary("reqtools.library", 0L))
{
tags[0] = RT_Screen;
tags[1] = (LONG)ReqToolsBase->IntuitionBase->FirstScreen;
tags[2] = TAG_DONE;
(void) rtPaletteRequestA("Palette", NULL, (struct TagItem *)tags);
CloseLibrary(ReqToolsBase);
}
palette_count--;
}
/*
* Asynchronous external command started with its own autocon Input/Output
* Result will only reflect whether System() call itself succeeded.
* If System() call fails, result will be -1L; -2L for window failure.
* We are using -2L as result if our Open of CON: fails
*/
#define AUTOCON "CON:0/25/640/150/Yak Command/AUTO/CLOSE/WAIT/ALT0/25/80/50"
static LONG
beginCommand(char *command)
{
static ULONG stags[] = {
SYS_Input, NULL,
SYS_Output, NULL,
SYS_Asynch, TRUE,
SYS_UserShell, TRUE,
NP_Priority, 0L,
TAG_DONE
};
BPTR file;
char *filename;
#ifdef NOTDEF /* will this screw up sometimes? */
char *t;
int inquote = FALSE, usecon = TRUE;
/* determine (simple-mindedly) whether there's redirection */
for (t = command; *t; t++)
{
if (*t == '\"')
if (t <= command || t[-1] != '*')
inquote ^= 1;
if (!inquote)
if (*t == '>')
{
usecon = FALSE;
break;
}
}
filename = usecon ? AUTOCON : "NIL:";
#else
filename = AUTOCON;
#endif
if (file = Open(filename, MODE_OLDFILE))
{
stags[1] = (ULONG)file;
return(SystemTagList(command, (struct TagItem *)stags));
}
else return(-2);
}
/*
* the hotkey actions themselves
*/
/* asynchronously execute a dos command */
static void
act_DosCommand(YakHotKey *yhk)
{
if (yhk->yhk_ArgStr)
{
LONG rc = beginCommand(yhk->yhk_ArgStr);
if (rc == -1)
PostError("Could not start process for command\n\"%s\"",
yhk->yhk_ArgStr);
else if (rc == -2)
PostError("Could not open con: for command\n\"%s\"",
yhk->yhk_ArgStr);
}
else PostError("No command specified for hotkey \"%s\".", yhk->yhk_KeyDef);
}
static void
act_CloseWindow(YakHotKey *yhk)
{
struct InputEvent ev;
struct Window *window;
ULONG lock;
lock = LockIBase(0);
window = IntuitionBase->ActiveWindow;
UnlockIBase(lock);
if (window && (window->IDCMPFlags & CLOSEWINDOW))
{
ev.ie_NextEvent = NULL;
ev.ie_Class = IECLASS_CLOSEWINDOW;
ev.ie_SubClass = 0;
ev.ie_Code = 0;
ev.ie_Qualifier = 0;
ev.ie_EventAddress = 0;
AddIEvents(&ev);
}
}
static void
act_ZipWindow(YakHotKey *yhk)
{
HandleWindowKey(HOW_ZIP);
}
static void
act_ShrinkWindow(YakHotKey *yhk)
{
HandleWindowKey(HOW_SHRINK);
}
static void
act_ExpandWindow(YakHotKey *yhk)
{
HandleWindowKey(HOW_ENLARGE);
}
static void
act_CycleWindows(YakHotKey *yhk)
{
#define NOCYCLEFLAGS (WFLG_BACKDROP)
struct Screen *s;
struct Window *w, *backmost;
struct Layer *l;
ULONG lock;
lock = LockIBase(0);
if (s = IntuitionBase->FirstScreen)
{
Forbid();
backmost = NULL;
for (l = s->LayerInfo.top_layer; l; l = l->back)
{
w = (struct Window *)l->Window;
if (w && !(w->Flags & NOCYCLEFLAGS))
backmost = w;
}
if (backmost)
{
ScreenToFront(s);
WindowToFront(backmost);
ActivateWindow(backmost);
}
Permit();
}
UnlockIBase(lock);
}
/* taglist for CreateNewProc */
static LONG palette_taglist[] = {
NP_Entry, (LONG)DoPalette,
NP_Name, (LONG)"Yak Palette",
TAG_DONE
};
static void
act_OpenPalette(YakHotKey *yhk)
{
CreateNewProc((struct TagItem *)palette_taglist);
}
static void
act_ScreenToFront(YakHotKey *yhk)
{
struct Screen *s;
ULONG lock;
lock = LockIBase(0);
for (s = IntuitionBase->FirstScreen; s; s = s->NextScreen)
if (!s->NextScreen)
{
ScreenToFront(s);
if (scractivate)
ActivateMouseWindow(SCREEN);
break;
}
UnlockIBase(lock);
}
static void
act_ScreenToBack(YakHotKey *yhk)
{
MyScreenToBack(IntuitionBase->FirstScreen);
}
static void
act_ActivateWorkbench(YakHotKey *yhk)
{
struct Window *w;
if (w = FindWBWindow())
{
WBenchToFront();
ActivateWindow(w);
}
}
static void
act_CentreScreen(YakHotKey *yhk)
{
struct Rectangle rect;
struct Screen *s;
ULONG lock;
ULONG modeid;
WORD newle;
lock = LockIBase(0);
if ((s = IntuitionBase->FirstScreen) &&
(modeid = GetVPModeID(&s->ViewPort)) != INVALID_ID &&
QueryOverscan(modeid, &rect, OSCAN_TEXT))
{
newle = (rect.MinX + rect.MaxX + 1 - s->Width) >> 1;
MoveScreen(s, newle - s->LeftEdge, 0);
}
UnlockIBase(lock);
}
static void
act_BlankDisplay(YakHotKey *yhk)
{
BlankScreen();
}
static void
act_InsertText(YakHotKey *yhk)
{
if (yhk->yhk_ArgStr)
{
if (!AddToStream(yhk->yhk_ArgStr))
PostError("Yak text insertion string invalid:\n \"%s\"", yhk->yhk_ArgStr);
}
else PostError("Yak text hotkey \"%s\" has no text specified.", yhk->yhk_KeyDef);
}
static void
act_InsertDate(YakHotKey *yhk)
{
struct DateTime dat;
DateStamp(&dat.dat_Stamp);
if (LocaleBase)
{
if (yhk->yhk_ArgStr)
FormatDate(locale, yhk->yhk_ArgStr, &dat.dat_Stamp, &putcharhook);
else PostError("Yak date hotkey \"%s\" has no format specified.", yhk->yhk_KeyDef);
}
else
{
/* pre-2.1 OS */
char datestr[LEN_DATSTRING];
dat.dat_Format = FORMAT_DOS;
dat.dat_Flags = 0;
dat.dat_StrDate = datestr;
dat.dat_StrDay = dat.dat_StrTime = NULL;
DateToStr(&dat);
AddToStream(datestr);
}
}
static void
act_ShowInterface(YakHotKey *yhk)
{
ShowWindow();
}
/*
* the generic hotkey action stub
*/
void
PerformAction(YakHotKey *yhk)
{
if (yhk->yhk_Options)
{
struct Screen *scr;
char *scrname;
if (yhk->yhk_Options == WB_TO_FRONT)
scrname = "Workbench";
else
scrname = NULL;
if (scr = LockPubScreen(scrname))
{
ScreenToFront(scr);
UnlockPubScreen(NULL, scr);
}
}
/* and perform action (gobbledegook!? that's C for you...) */
(*(yhktypes[yhk->yhk_Type].yhkt_Command))(yhk);
}
/*
* YakHotKey manipulation routines
*/
static void internal_DeleteYakHotKey(YakHotKey *yhk);
/* allocate memory region of size len+1, copy string to it */
char *
DupStr(char *str)
{
char *newstr;
ULONG len;
if (newstr = AllocVec(len=(strlen(str)+1),MEMF_CLEAR))
{
CopyMem(str,newstr,len);
}
return newstr;
}
/* free fields of hotkey */
static void
internal_DeleteYakHotKey(YakHotKey *yhk)
{
if (yhk->yhk_ArgStr)
FreeStr(yhk->yhk_ArgStr);
if (yhk->yhk_KeyDef)
FreeStr(yhk->yhk_KeyDef);
if (yhk->yhk_CxObj)
DeleteCxObjAll(yhk->yhk_CxObj);
}
/* free ALL memory associated with a hotkey and remove from list */
void
DeleteYakHotKey(YakHotKey *yhk)
{
numkeys(yhk->yhk_Type)--;
num_hkeys--;
Remove((struct Node *)yhk);
internal_DeleteYakHotKey(yhk);
FreeVec(yhk);
}
/* change key definition */
int
ModifyYHKKeyDef(YakHotKey *yhk, char *keystr)
{
CxObj *filter;
if (filter = HotKey(keystr, broker_mp, (LONG)yhk))
{
/* delete old filter and use new one */
if (yhk->yhk_CxObj)
DeleteCxObjAll(yhk->yhk_CxObj);
yhk->yhk_CxObj = filter;
AttachCxObj(broker, filter);
/* and store new keystr */
if (yhk->yhk_KeyDef)
FreeStr(yhk->yhk_KeyDef);
if (yhk->yhk_KeyDef = DupStr(keystr))
{
yhk->yhk_Node.ln_Name = yhk->yhk_KeyDef;
return TRUE;
}
PostError("Allocation error");
}
else PostError("Invalid hotkey specification: \"%s\"", keystr);
return FALSE;
}
/* change argument string */
int
ModifyYHKArgStr(YakHotKey *yhk, char *argstr)
{
char *newstr;
if (argstr && *argstr)
{
if (newstr = DupStr(argstr))
{
FreeStr(yhk->yhk_ArgStr);
yhk->yhk_ArgStr = newstr;
return TRUE;
}
PostError("Allocation error");
}
else PostError("An argument should be specified for this key.");
return FALSE;
}
/* add a new hotkey of given type */
YakHotKey *
NewYakHotKey(UWORD type)
{
YakHotKey *newhk;
if (newhk = AllocVec(sizeof(YakHotKey), MEMF_CLEAR))
{
newhk->yhk_Node.ln_Name = "<unset>";
newhk->yhk_Type = type;
AddTail(keylist(type), (struct Node *)newhk);
numkeys(type)++;
num_hkeys++;
}
return newhk;
}
/* initialise list */
void
InitYakHotKeyList()
{
UWORD i;
for (i = 0; i < NUM_HOTKEY_TYPES; i++)
NewList(keylist(i));
}
/* delete whole list */
void
DeleteYakHotKeyList()
{
YakHotKey *yhk;
UWORD i;
for (i = 0; i < NUM_HOTKEY_TYPES; i++)
while (yhk = (YakHotKey *)RemHead(keylist(i)))
DeleteYakHotKey(yhk);
}
/* okay to quit? (not so if palettes open) */
int
OkayToExit()
{
return (palette_count == 0);
}