home *** CD-ROM | disk | FTP | other *** search
- /* -----------------------------------------------------------------------------
-
- Mirror API client, ©1995 Dietmar Eilert. Dice:
-
- dcc main.c -// -proto -mi -l reqtoolssr.lib -r -2.0 -o ram:mirror
-
- ------------------------------------------------------------------------------
- */
-
- /// "includes"
-
- #define Prototype extern
-
- #include <exec/exec.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <dos/dos.h>
- #include <dos/dostags.h>
- #include <dos/rdargs.h>
- #include <intuition/intuition.h>
- #include <utility/tagitem.h>
- #include <workbench/startup.h>
- #include <rexx/errors.h>
- #include <rexx/rxslib.h>
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/rexxsyslib_protos.h>
- #include <clib/alib_protos.h>
- #include <clib/reqtools_protos.h>
-
- #include "golded:api/include/golded.h"
-
- struct Settings {
-
- UWORD Range; // range of lines to be considered
- BOOL Online; // scanner online ?
- UBYTE Twins[255]; // characters to look for
- };
-
- Prototype void main(int, char **);
- Prototype int wbmain(struct WBStartup *);
- Prototype void HandleAPI(char *, struct Settings *);
- Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
- Prototype BOOL MatchingBracket(struct APIMessage *, struct Settings *, UWORD, BOOL);
- Prototype void Dispatch(struct APIMessage *, struct Settings *);
- Prototype LONG CommandMatch(ULONG *, struct APIMessage *, struct Settings *);
- Prototype BOOL IsABracket(UBYTE, struct Settings *);
- Prototype BOOL FindMarkedBracket(struct EditConfig *, struct Settings *);
- Prototype BOOL NoUserBlock(struct EditConfig *, struct Settings *);
-
- // globals
-
- struct Library *ReqToolsBase;
-
- ///
- /// "main"
-
- int
- wbmain(struct WBStartup *startup)
- {
- if (ReqToolsBase = OpenLibrary("reqtools.library", 37)) {
-
- rtEZRequestTags("No executable - to be used as API client", "OK", NULL, NULL, TAG_DONE);
-
- CloseLibrary(ReqToolsBase);
- }
- }
-
- void
- main(int argc, char **argv)
- {
- static UBYTE version[] = "$VER: Mirror 1.3 (" __COMMODORE_DATE__ ")";
-
- ULONG argArray[] = { 0, 0, 0, 0, 0 };
-
- struct RDArgs *rdArgs;
-
- if (rdArgs = ReadArgs("H=HOST/K/A,RANGE/N,ONLINE/S,OFFLINE/S,TWINS/K", argArray, NULL)) {
-
- struct Settings settings = { 30, TRUE, "(){}[]" };
-
- if (argArray[1]) // RANGE/N
- settings.Range = *(ULONG *)argArray[1];
-
- if (argArray[2])
- settings.Online = TRUE; // ONLINE/S
-
- if (argArray[3])
- settings.Online = FALSE; // OFFLINE/S
-
- if (argArray[4]) // TWINS/K
- strcpy(settings.Twins, (char *)argArray[4]);
-
- HandleAPI((UBYTE *)argArray[0], &settings);
-
- FreeArgs(rdArgs);
- }
-
- exit(0);
- }
-
- ///
- /// "api management"
-
- /* --------------------------------- HandleAPI ---------------------------------
-
- Register with GoldED & handle incoming API messages.
-
- */
-
- void
- HandleAPI(host, settings)
-
- char *host;
- struct Settings *settings;
- {
- struct MsgPort *apiPort, *rexxPort;
-
- if (apiPort = CreateMsgPort()) {
-
- if (rexxPort = CreateMsgPort()) {
-
- UBYTE command[255];
- ULONG *result;
-
- sprintf(command, "API PORT=%ld CLASS=%ld", apiPort, API_CLASS_ROOT | API_CLASS_KEY | API_CLASS_REXX);
-
- if (result = SendRexxCommand(host, command, rexxPort, NULL)) {
-
- if (*result == RC_OK) {
-
- BOOL active = TRUE;
-
- do {
-
- struct APIMessage *apiMsg, *nextMsg;
-
- while (!(apiMsg = (struct APIMessage *)GetMsg(apiPort)))
- WaitPort(apiPort);
-
- do {
-
- for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
-
- if (nextMsg->api_State == API_STATE_NOTIFY) {
-
- switch (nextMsg->api_Class) {
-
- case API_CLASS_ROOT:
-
- switch (nextMsg->api_Action) {
-
- case API_ACTION_DIE:
-
- active = FALSE;
- break;
-
- case API_ACTION_INTRODUCE:
-
- static struct TagItem tags[] = {
-
- API_Client_Name, "Mirror",
- API_Client_Copyright, "Mirror ©1995 Dietmar Eilert",
- API_Client_Purpose, "Online bracket highlighting",
- API_Client_Template, "MIRROR CHECK/S,RANGE/N,ONLINE/S,OFFLINE/S",
- TAG_DONE
- };
-
- nextMsg->api_Data = tags;
- break;
-
- default:
-
- nextMsg->api_Error = API_ERROR_UNKNOWN;
- }
-
- break;
-
- case API_CLASS_KEY:
-
- switch (nextMsg->api_Action) {
-
- case API_ACTION_VANILLAKEY:
-
- if ((settings->Online) && NoUserBlock(apiMsg->api_Config, settings)) {
-
- if (IsABracket((UBYTE)nextMsg->api_Data, settings) && MatchingBracket(nextMsg, settings, (UBYTE)nextMsg->api_Data, TRUE))
-
- break;
-
- else if (FindMarkedBracket(nextMsg->api_Config, settings))
-
- apiMsg->api_Refresh |= API_REFRESH_NOMARKER;
- }
- break;
-
- default:
-
- nextMsg->api_Error = API_ERROR_UNKNOWN;
- }
- break;
-
- case API_CLASS_REXX:
-
- switch (nextMsg->api_Action) {
-
- case API_ACTION_COMMAND:
-
- Dispatch(nextMsg, settings);
- break;
-
- default:
-
- nextMsg->api_Error = API_ERROR_UNKNOWN;
- }
- break;
-
- default:
-
- nextMsg->api_Error = API_ERROR_UNKNOWN;
- }
- }
- }
-
- ReplyMsg((struct Message *)apiMsg);
-
- } while (apiMsg = (struct APIMessage *)GetMsg(apiPort));
-
- } while (active);
- }
- }
-
- DeleteMsgPort(rexxPort);
- }
-
- DeleteMsgPort(apiPort);
- }
- }
-
-
- ///
- /// "arexx class"
-
- /* --------------------------------- Dispatch ----------------------------------
-
- Dispatch incoming command: examine command string (command part is uppercase
- already), look for handler function related to command, parse arguments (if
- command supports arguments), call handler.
-
- */
-
- void
- Dispatch(apiMsg, settings)
-
- struct Settings *settings;
- struct APIMessage *apiMsg;
- {
- struct RDArgs *rdArgs, *args;
-
- if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
-
- static char buffer[1024];
-
- // table of supported commands, associated handlers & template strings
-
- static struct parser { char *command; LONG (*handler)(ULONG *, struct APIMessage *, struct Settings *); char *template; } parser[] = {
-
- "MIRROR", (APTR)CommandMatch, "CHECK/S,RANGE/N,ONLINE/S,OFFLINE/S,AUTOHIDE/S,TWINS/K",
- NULL
- };
-
- ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0 };
-
- struct APIRexxNotify *notify = (struct APIRexxNotify *)apiMsg->api_Data;
-
- // make LF-terminated copy of command string (required by dos/readArgs):
-
- strcpy(buffer, notify->arn_Command);
- strcat(buffer, "\12");
-
- for (n = 0; parser[n].command; ++n) {
-
- if (!memcmp(buffer, parser[n].command, strlen(parser[n].command))) {
-
- char *arguments = buffer + strlen(parser[n].command);
-
- rdArgs->RDA_Source.CS_Buffer = arguments;
- rdArgs->RDA_Source.CS_Length = strlen(arguments);
- rdArgs->RDA_Source.CS_CurChr = 0;
- rdArgs->RDA_DAList = NULL;
- rdArgs->RDA_Buffer = NULL;
-
- if (parser[n].template) {
-
- if (args = ReadArgs(parser[n].template, argArray, rdArgs)) {
-
- notify->arn_RC = (*parser[n].handler)(argArray, apiMsg, settings);
-
- FreeArgs(args);
- }
- else {
-
- static UBYTE errorText[81];
-
- notify->arn_RC = RC_WARN;
- notify->arn_CommandError = errorText;
-
- Fault(IoErr(), "IoErr()", errorText, 80);
- }
- }
- else
- notify->arn_RC = (*parser[n].handler)(argArray, apiMsg, settings);
- }
- }
-
- FreeDosObject(DOS_RDARGS, rdArgs);
- }
- }
-
- /* -------------------------------- CommandMatch -------------------------------
-
- Highlight matching bracket
-
- template: CHECK/S,RANGE/N,ONLINE/S,OFFLINE/S,AUTOHIDE/S,TWINS/K
-
- */
-
- LONG
- CommandMatch(argArray, apiMsg, settings)
-
- ULONG *argArray;
-
- struct APIMessage *apiMsg;
- struct Settings *settings;
- {
- UBYTE letter = apiMsg->api_Config->CurrentBuffer[apiMsg->api_Config->Column];
-
- apiMsg->api_State = API_STATE_CONSUMED;
-
- if (argArray[5]) // TWINS/K
- strcpy(settings->Twins, (char *)argArray[5]);
-
- if (argArray[0] && IsABracket(letter, settings) && NoUserBlock(apiMsg->api_Config, settings))
-
- MatchingBracket(apiMsg, settings, letter, FALSE);
-
- else if (argArray[4] && FindMarkedBracket(apiMsg->api_Config, settings))
-
- apiMsg->api_Refresh |= API_REFRESH_NOMARKER; // AUTOHIDE/S
-
- if (argArray[1]) // RANGE/N
- settings->Range = *(ULONG *)argArray[1];
-
- if (argArray[2])
- settings->Online = TRUE; // ONLINE/S
-
- if (argArray[3]) // OFFLINE/S
- settings->Online = FALSE;
-
- return(RC_OK);
- }
-
- ///
- /// "online check"
-
- /* ------------------------------- MatchingBracket --------------------------------
-
- Find matching bracket. Only <distance> lines are considered. Ignore opening
- brackets preceeded by '/' (ASCII 92, TeX style construction used to insert a
- bracket into text). Set <pending> to TRUE if current character hasn't yet been
- inserted.
-
- */
-
- BOOL
- MatchingBracket(apiMsg, settings, examine, pending)
-
- UWORD examine;
- BOOL pending;
- struct APIMessage *apiMsg;
- struct Settings *settings;
- {
- UBYTE *current, *known;
- WORD column, step, len;
- BOOL success, inString;
- ULONG line;
-
- struct EditConfig *config = apiMsg->api_Config;
-
- inString = FALSE;
- success = FALSE;
- known = settings->Twins;
-
- line = config->Line;
- column = config->Column;
- len = config->CurrentLen;
- current = config->CurrentBuffer;
-
- for (step = 1; *known; ++known, step = -step) {
-
- if ((examine == *known) && ((column == 0) || (current[column - 1] != 92))) {
-
- WORD level, count, distance;
- char twin;
-
- twin = *(known + step);
- count = 0;
- level = (pending) ? 0 : -1;
- distance = settings->Range;
-
- for (distance = 0; distance <= settings->Range; ++distance) {
-
- while ((column >= 0) && (column < len)) {
-
- char *next = current + column;
-
- if ((*next == 34) || (*next == 39))
-
- inString = !inString;
-
- else if (!inString) {
-
- if ((*next == twin) && !(column && (*(next - 1) == 92))) {
-
- if (level)
- --level;
-
- else {
-
- success = TRUE;
- break;
- }
- }
- else if ((*next == *known) && !(column && (*(next - 1) == 92))) {
-
- ++level;
- ++count;
- }
- }
-
- column += step;
- }
-
- if (success) {
-
- BOOL adjacent = FALSE;
-
- if (line == config->Line) {
-
- if (pending)
- adjacent = ((step == -1) && (config->Column + step == column)) || ((step == 1) && (column == config->Column));
- else
- adjacent = (column == (config->Column + step));
- }
-
- if (adjacent)
-
- apiMsg->api_Refresh |= API_REFRESH_NOMARKER;
-
- else {
-
- if ((distance == 0) && ((config->Marker == BLOCKMODE_NONE) || ((line == config->BlockStartY) && (line == config->BlockEndY))))
-
- apiMsg->api_Refresh = API_REFRESH_LINE;
- else
- apiMsg->api_Refresh = API_REFRESH_DISPLAY;
-
- config->BlockStartX = config->BlockEndX = column;
- config->BlockStartY = config->BlockEndY = line;
-
- config->Marker = BLOCKMODE_CHAR;
- }
-
- return(TRUE);
- }
- else {
-
- line += step;
- inString = FALSE;
-
- if ((line >= 0) && (line < config->Lines)) {
-
- current = (config->TextNodes + line)->Text;
- len = (config->TextNodes + line)->Len;
-
- column = (step == -1) ? len - 1 : 0;
- }
- else // no matching bracket
- break;
- }
- }
-
- apiMsg->api_Refresh |= API_REFRESH_NOMARKER;
-
- break;
- }
- }
-
- return(FALSE);
- }
-
-
- ///
- /// "misc"
-
- /* ------------------------------- NoUserBlock ---------------------------------
-
- Return TRUE if there is no user-defined block, i.e. either no block at all or a
- marked bracket only (possibly marked by us).
-
- */
-
- BOOL
- NoUserBlock(config, settings)
-
- struct EditConfig *config;
- struct Settings *settings;
- {
- return((config->Marker == BLOCKMODE_NONE) || FindMarkedBracket(config, settings));
- }
-
-
- /* -------------------------------- IsABracket ---------------------------------
-
- Check whether character is a bracket
-
- */
-
- BOOL
- IsABracket(letter, settings)
-
- UBYTE letter;
- struct Settings *settings;
- {
- UBYTE *known;
-
- for (known = settings->Twins; *known; ++known)
- if (letter == *known)
- return(TRUE);
-
- return(FALSE);
- }
-
- /* ----------------------------- FindMarkedBracket -----------------------------
-
- Return TRUE if a single bracket has been marked
-
- */
-
- BOOL
- FindMarkedBracket(config, settings)
-
- struct EditConfig *config;
- struct Settings *settings;
- {
- if (config->Marker == BLOCKMODE_CHAR) {
-
- if (config->BlockStartY == config->BlockEndY) {
-
- if (config->BlockStartX == config->BlockEndX) {
-
- UWORD pos = config->BlockStartX;
-
- if (config->BlockStartY == config->Line) {
-
- if (pos < config->CurrentLen)
- return(IsABracket(config->CurrentBuffer[pos], settings));
- }
- else {
-
- struct LineNode *lineNode = config->TextNodes + config->BlockStartY;
-
- if (pos < lineNode->Len)
- return(IsABracket(lineNode->Text[config->BlockStartX], settings));
- }
-
- }
-
- }
- }
-
- return(FALSE);
- }
-
-
-
- ///
- /// "arexx"
-
- /* ---------------------------------- SendRexxCommand -------------------------
-
- Send ARexx message & wait for answer. Return pointer to result or NULL.
-
- */
-
- ULONG *
- SendRexxCommand(port, cmd, replyPort, buffer)
-
- char *cmd, *port, *buffer;
- struct MsgPort *replyPort;
- {
- struct MsgPort *rexxport;
-
- Forbid();
-
- if (rexxport = FindPort(port)) {
-
- struct RexxMsg *rexxMsg, *answer;
-
- if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
-
- if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
-
- static ULONG result;
-
- rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
-
- PutMsg(rexxport, &rexxMsg->rm_Node);
-
- do {
-
- WaitPort(replyPort);
-
- if (answer = (struct RexxMsg *)GetMsg(replyPort))
- result = answer->rm_Result1;
-
- } while (!answer);
-
- Permit();
-
- if (answer->rm_Result1 == RC_OK) {
-
- if (answer->rm_Result2) {
-
- if (buffer)
- strcpy(buffer, (char *)answer->rm_Result2);
-
- DeleteArgstring((char *)answer->rm_Result2);
- }
- }
-
- DeleteArgstring((char *)ARG0(answer));
-
- DeleteRexxMsg(answer);
-
- return(&result);
- }
- }
- }
-
- Permit();
-
- return(NULL);
- }
-
- ///
-