Logo Search packages:      
Sourcecode: xconq version File versions  Download package

mac.c

/* Mac-specific code for Xconq kernel.
   Copyright (C) 1992-1997, 1999 Stanley T. Shebs.

Xconq is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.  See the file COPYING.  */

/* The code in this file is Mac-specific, but not necessarily specific
   to any particular app; it should be usable with utilities and with
   apps that don't have fancy interface. */

#include "config.h"
#include "misc.h"
#include "dir.h"
#include "lisp.h"
#include "module.h"
#include "system.h"

#if 0  /* Unused. */
void mac_abort(void);
#endif

/* Following are from tp.h, but tp.h is too high-level to include. */

#if 0  /* shouldn't be here */
extern int numremotes;
extern int my_rid;
extern int master_rid;
#endif

extern void init_file_port(int willhost);
extern void close_file_port(void);
extern void low_file_send(int id, char *buf);
extern int low_file_receive(int *id, char *buf, int maxchars, int timeout);

/* Private functions. */

static void init_serial_port(int port);
static void close_serial_port(void);
static void open_appletalk(void);
static int low_appletalk_receive(int *id, char *buf, int maxchars, int timout);
static void low_appletalk_send(int id, char *buf);
static void close_appletalk(void);
static void low_serial_send(int id, char *buf);
static int low_serial_readchars(char *buf, int maxchars, int timeout);

#ifdef THINK_C
#include <MacHeaders>
#endif /* THINK_C */

#ifdef MPW
#ifdef NEW_HEADERS
#include <MacTypes.h>
#else
#include <Types.h>
#endif /* NEW_HEADERS */
#include <Resources.h>
#include <Events.h>  /* for TickCount */
#include <TextUtils.h>  /* for GetIndString */
#endif /* MPW */

#ifdef __MWERKS__
#ifdef NEW_HEADERS
#include <MacTypes.h>
#else
#include <Types.h>
#endif /* NEW_HEADERS */
#include <Resources.h>
#include <Events.h>  /* for TickCount */
#include <TextUtils.h>  /* for GetIndString */
#include <Quickdraw.h>
#include <StandardFile.h>
#include <Devices.h>
#endif /* __MWERKS__ */

#include <signal.h>

/* We need this in order to find string resources that have filenames
   in them. */
#include "macdefs.h"

#include <Serial.h>

#include <AppleTalk.h>

#ifdef MPW_C
#define QD(whatever) (qd.##whatever)
#define QDPat(whatever) (&(qd.##whatever))
#endif
#ifdef THINK_C
#define QD(whatever) (whatever)
#define QDPat(whatever) (whatever)
#endif
#ifdef __MWERKS__
#define QD(whatever) (qd.##whatever)
#define QDPat(whatever) (&(qd.##whatever))
#endif

#ifndef c2p
#define c2p(STR,PBUF) \
  strcpy(((char *) PBUF) + 1, STR);  \
  PBUF[0] = strlen(STR);
#endif

#ifndef p2c
#define p2c(PSTR,BUF)  \
  strncpy(BUF, ((char *) (PSTR) + 1), PSTR[0]);  \
  BUF[PSTR[0]] = '\0';
#endif

extern CursHandle sendcursor;
extern CursHandle receivecursor;
extern CursHandle current_cursor;

int connection_method;

/* The HFS volume that the program started with. */

short initialvrefnum;

static char *news_fname;
static char *save_fname;
static char *checkpoint_fname;
static char *error_save_fname;
static char *statistics_fname;

/* We normally keep the library and image folders in the same folder
   as the app. */

#ifndef XCONQLIB
#define XCONQLIB ":lib"
#endif

#ifndef XCONQIMAGES
#define XCONQIMAGES ":images"
#endif

char *
default_library_pathname()
{
    return XCONQLIB;
}

char *
default_images_pathname()
{
    return XCONQIMAGES;
}

char *
news_filename()
{
    Str255 tmpstr;
    char tmpbuf[255];
    
    if (news_fname == NULL) {
      GetIndString(tmpstr, sFilenames, siNews);
      p2c(tmpstr, tmpbuf);
      if (!empty_string(tmpbuf))
        news_fname = copy_string(tmpbuf);
      else
        news_fname = NEWSFILE;
    }
    return news_fname;
}

char *
saved_game_filename()
{
    Str255 tmpstr;
    char tmpbuf[255];
    
    if (save_fname == NULL) {
      GetIndString(tmpstr, sFilenames, siSavedGame);
      p2c(tmpstr, tmpbuf);
      if (!empty_string(tmpbuf))
        save_fname = copy_string(tmpbuf);
      else
        save_fname = "Saved Game";
    }
    return save_fname;
}

/* (should make use of turn number in checkpoint filename) */

char *
checkpoint_filename(int n)
{
    Str255 tmpstr;
    char tmpbuf[255];

    if (checkpoint_fname == NULL) {
      GetIndString(tmpstr, sFilenames, siCheckpoint);
      p2c(tmpstr, tmpbuf);
      if (!empty_string(tmpbuf))
        checkpoint_fname = copy_string(tmpbuf);
      else
        checkpoint_fname = "Checkpoint";
    }
    return checkpoint_fname;
}

char *
error_save_filename()
{
    Str255 tmpstr;
    char tmpbuf[255];

    if (error_save_fname == NULL) {
      GetIndString(tmpstr, sFilenames, siErrorSave);
      p2c(tmpstr, tmpbuf);
      if (!empty_string(tmpbuf))
        error_save_fname = copy_string(tmpbuf);
      else
        error_save_fname = "Error Save";
    }
    return error_save_fname;
}

char *
statistics_filename()
{
    Str255 tmpstr;
    char namebuf[256];
    Point pnt;
    SFReply reply;

    if (statistics_fname == NULL) {
      GetIndString(tmpstr, sFilenames, siStatistics);
      p2c(tmpstr, namebuf);
      if (!empty_string(namebuf))
        statistics_fname = copy_string(namebuf);
      else
        statistics_fname = "Statistics";
      /* Collect the file and path to save to. */
      SetPt(&pnt, 100, 100);
      c2p(statistics_fname, tmpstr);
      SFPutFile(pnt, "\pSave game statistics as:", tmpstr, /*(DlgHookProcPtr)*/ nil, &reply);
      if (!reply.good)
        return NULL;
      /* Make the location of the file be the current volume. */
      SetVol(reply.fName, reply.vRefNum);
      p2c(((char *) reply.fName), namebuf);
      statistics_fname = copy_string(namebuf);
    }
    return statistics_fname;
}

/* The purpose of this wrapper for fopen is to handle cases where the 
mac is opening a unix file and automatic linefeed conversion therefore
should be disabled. */

FILE *
open_file(char *filename, char *mode)
{
      FILE  *fp;
      short curvrefnum;
      int   mac_linefeeds = 0;
      int   unix_linefeeds = 0;
      int   ch;

      /* Hack. Force debug output to top directory. */ 
      if (strcmp(filename, "Xconq.DebugOut") == 0)
          SetVol(NULL, initialvrefnum);

      /* Hack. Force warning output to top directory. */ 
      if (strcmp(filename, "Xconq.Warnings") == 0)
          SetVol(NULL, initialvrefnum);

      /* Writing or Appending: always mac format. */  
      if (strcmp(mode, "w") == 0) {
            fp = fopen(filename, "w");
            return fp;
      }           
      if (strcmp(mode, "a") == 0) {
            fp = fopen(filename, "a");
            return fp;
      }           
      /* Reading: first open in binary mode (no conversion). */
      fp = fopen(filename, "rb");
      /* Look in xconq start directory if we did not find a file. */
      if (fp == NULL) {
            GetVol(NULL, &curvrefnum);
            SetVol(NULL, initialvrefnum);
            fp = fopen(filename, "rb");
            SetVol(NULL, curvrefnum);
      }
      /* Give up if we found nothing there either. */
      if (fp == NULL)
          return fp;
      /* Binary (image) files don't need conversion. */
      if (strcmp(mode, "rb") == 0)
          return fp;
      /* Text file. Count the number of linefeeds of each kind. */
      while ((ch = getc(fp)) != EOF) {
            if (ch == '\r')
                  ++mac_linefeeds;
            if (ch == '\n')
                  ++unix_linefeeds;
      }
      /* Close the file (also needed in unix case to reset file pointer). */
      fclose(fp);
      /* Assume that a mac file has more mac than unix linefeeds. */
      if (mac_linefeeds > unix_linefeeds) {
            /* Reopen mac file in text mode (with conversion). */
            fp = fopen(filename, "r");
      } else      {
            /* Reopen unix file in binary mode (no conversion). */
            fp = fopen(filename, "rb");
      }
      return fp;        
}

/* Attempt to open a library file. */

FILE *
open_module_library_file(Module *module)
{
    short curvrefnum;
    char fullnamebuf[255];
    LibraryPath *p;
    FILE *fp;
    
    /* Can't open anonymous library modules. */
    if (module->name == NULL)
      return NULL;
    /* Generate library pathname. */
    for_all_library_paths(p) {
      make_pathname(p->path, module->name, "g", fullnamebuf);
      /* Now try to open the file. */
      fp = open_file(fullnamebuf, "r");
      if (fp != NULL) {
          /* Remember the filename where we found it. */
          module->filename = copy_string(fullnamebuf);
          return fp;
      }
    }
    return NULL;
}

FILE *
open_module_explicit_file(Module *module)
{
    short curvrefnum;
    char fullnamebuf[255];
    LibraryPath *p;
    FILE *fp = NULL;
    
    if (module->filename == NULL) {
      /* Try guessing a filename, since none supplied. */
      if (module->name != NULL) {
          for_all_library_paths(p) {
            make_pathname(p->path, module->name, "g", fullnamebuf);
            /* Now try to open the file. */
            fp = open_file(fullnamebuf, "r");
            if (fp != NULL)
              return fp;
          }
      }
    } else {
      /* Try some other random ideas. */
      sprintf(fullnamebuf, "%s", module->filename);
      fp = open_file(module->filename, "r");
      if (fp != NULL) {
          add_library_path("");
          return fp;
      }
      sprintf(fullnamebuf, ":%s", module->filename);
      fp = open_file(fullnamebuf, "r");
      if (fp != NULL)
        return fp;
      sprintf(fullnamebuf, "%s%s", ":lib:", module->filename);
      fp = open_file(fullnamebuf, "r");
      if (fp != NULL)
        return fp;
    }
    return NULL;
}

FILE *
open_library_file(char *filename)
{
    short curvrefnum;
    char fullnamebuf[255];
    LibraryPath *p;
    FILE *fp;
      
    /* Now try to open the file. */
    fp = open_file(filename, "r");
    if (fp != NULL)
      return fp;
    /* Generate library pathname. */
    for_all_library_paths(p) {
      make_pathname(p->path, filename, NULL, fullnamebuf);
      /* Now try to open the file. */
      fp = open_file(fullnamebuf, "r");
      if (fp != NULL)
        return fp;
    }
    return NULL;
}

FILE *
open_scorefile_for_reading(char *name)
{
    char buf[255];
    short curvrefnum;
    FILE *fp;
      
    GetVol(NULL, &curvrefnum);
    SetVol(NULL, initialvrefnum);
    fp = open_file(name, "r");
    SetVol(NULL, curvrefnum);
    return fp;
}

FILE *
open_scorefile_for_writing(char *name)
{
    char buf[255];
    short curvrefnum;
    FILE *fp;
      
    GetVol(NULL, &curvrefnum);
    SetVol(NULL, initialvrefnum);
    /* Now try to open the file. */
    sprintf(buf, "%s", name);
    fp = open_file(buf, "a");
    SetVol(NULL, curvrefnum);
    return fp;
}

/* Close scorefile after having written to it; nothing special to do on Macs. */

void
close_scorefile_for_writing(fp)
FILE *fp;
{
    fclose(fp);
}

void
make_pathname(char *path, char *name, char *extn, char *pathbuf)
{
    strcpy(pathbuf, "");
    if (!empty_string(path)) {
      strcat(pathbuf, path);
      strcat(pathbuf, ":");
    }
    strcat(pathbuf, name);
    /* Don't add a second identical extension, but do add if extension
       is different (in case we want "foo.12" -> "foo.12.g" for instance) */
    if (strrchr(name, '.')
      && extn
      && strcmp(strrchr(name, '.') + 1, extn) == 0)
      return;
    if (!empty_string(extn)) {
      strcat(pathbuf, ".");
      strcat(pathbuf, extn);
    }
}

/* Remove a given file. */

int
remove_file(char *fname)
{
    /* (should implement) */
    return FALSE;
}

void
init_signal_handlers()
{
}

int last_ticks = 0;

int
n_seconds_elapsed(n)
int n;
{
    int ticks = TickCount();

    if (((ticks - last_ticks) / 60) > n) {
      last_ticks = ticks;
      return TRUE;
    } else {
      return FALSE;
    }
}

int last_ticks_for_ms = 0;

int
n_ms_elapsed(n)
int n;
{
    return (((TickCount() - last_ticks_for_ms) * 16) > n);
}

void
record_ms()
{
    last_ticks_for_ms = TickCount();
}

#if 0       /* Not called from anywhere. */

/* Instead of coredumping, which is not a normal Mac facility, we
   drop into Macsbug.  If we then "g" from Macsbug, the program will
   exit cleanly. */

void
mac_abort ()
{
    /* Make sure no output still buffered up, then zap into MacsBug. */
#if 0 /* how to know if stdio in use? */
    fflush(stdout);
    fflush(stderr);
    printf("## Abort! ##\n");
#endif
#ifdef MPW_SADE
    SysError(8005);
#else 
    Debugger();
#endif
    /* "g" in MacsBug will then cause a regular error exit. */
    exit(1);
}

#endif

int
open_remote_connection(char *methodname, int willhost)
{
    int serial_port, rslt;

    if (methodname == NULL) {
      connection_method = 0;
    } else if (strcmp(methodname, "serial") == 0) {
      connection_method = 1;
    } else if (strcmp(methodname, "appletalk") == 0) {
      connection_method = 2;
    } else if (strcmp(methodname, "tcp") == 0) {
      connection_method = 3;
    } else if (strcmp(methodname, "file") == 0) {
      connection_method = 4;
    } else {
      connection_method = 0;
    }
    switch (connection_method) {
      case 0:
      break;
      case 1:
      /* Get a decision about which serial port to use. */
      serial_port = serial_port_dialog();
      /* If cancelled here, get out and don't open anything. */
      if (serial_port < 0)
        break;
      init_serial_port(serial_port);
      /* Serial supports exactly two programs, so we can easily
         set up all the rids right now. */
#if 0 /* but that would be wrong */
      master_rid = 1;
      if (willhost) {
          my_rid = 1;
      } else {
          my_rid = 2;
      }
      numremotes = 2;
#endif
      break;
      case 2:
      open_appletalk();
      break;
      case 3:
      init_warning("No TCP/IP support yet, ignoring");
      break;
      case 4:
      init_file_port(willhost);
      break;
      default:
      break;
    }
    return connection_method;
}

extern short ser_input_refnum;
extern short ser_output_refnum;

/* Low-level transmission to another program. */

void
low_send(int id, char *buf)
{
    if (sendcursor != nil)
      SetCursor(*sendcursor);
    Dprintf("Sending: %d \"%s\"...", id, (buf ? buf : "<null>"));
    switch (connection_method) {
      case 0:
      /* Not connected anywhere, no need to complain. */
      break;
      case 1:
      low_serial_send(id, buf);
      break;
      case 2:
      low_appletalk_send(id, buf);
      break;
      case 3:
      break;
      case 4:
      low_file_send(id, buf);
      break;
      default:
      case_panic("connection method", connection_method);
      break;
    }
    Dprintf(" sent.\n");
    if (sendcursor != nil) {
      if (current_cursor != nil)
        SetCursor(*current_cursor);
      else
        SetCursor(&QD(arrow));
    }
}

int
low_receive(int *idp, char *buf, int maxchars, int timeout)
{
    int rslt = FALSE;

    if (receivecursor != nil)
      SetCursor(*receivecursor);
    switch (connection_method) {
      case 0:
      /* Not connected anywhere, no need to complain. */
      break;
      case 1:
      /* Only one remote if using serial. */
      *idp = (0 /*my_rid == 1 */? 2 : 1);
      rslt = low_serial_readchars(buf, maxchars, timeout);
      break;
      case 2:
      /* Only one remote for now. */
      *idp = (0 /*my_rid == 1*/ ? 2 : 1);
      rslt = low_appletalk_receive(idp, buf, maxchars, timeout);
      break;
      case 3:
      break;
      case 4:
      rslt = low_file_receive(idp, buf, maxchars, timeout);
      break;
      default:
      case_panic("connection method", connection_method);
      break;
    }
    if (receivecursor != nil) {
      if (current_cursor != nil)
        SetCursor(*current_cursor);
      else
        SetCursor(&QD(arrow));
    }
    return rslt;
}

void
close_remote_connection(int rid)
{
    switch (connection_method) {
      case 0:
      break;
      case 1:
      close_serial_port();
      break;
      case 2:
      close_appletalk();
      break;
      case 3:
      break;
      case 4:
      close_file_port();
      break;
      default:
      break;
    }
}

short ser_input_refnum;
short ser_output_refnum;

static void
init_serial_port(port)
int port;
{
    OSErr err;

    if (port == 0) {
      /* Open the modem port. */
      err = OpenDriver("\p.AIn", &ser_input_refnum);
      if (err != 0) {
          return;
      }
      err = OpenDriver("\p.AOut", &ser_output_refnum);
      if (err != 0) {
          /* This isn't working, so close the input as well. */
          CloseDriver(ser_input_refnum);
          return;
      }
    } else {
      /* Open the printer port. */
      err = OpenDriver("\p.BIn", &ser_input_refnum);
      if (err != 0) {
          return;
      }
      err = OpenDriver("\p.BOut", &ser_output_refnum);
      if (err != 0) {
          /* This isn't working, so close the input as well. */
          CloseDriver(ser_input_refnum);
          return;
      }
    }
#if 0 /* might need this eventually? */
    if (0 /* using custom buffer */)
      SerSetBuf (ser_input_refnum, mac_input_buffer, 256);
#endif
    SerReset (ser_input_refnum,  stop10|noParity|data8|baud9600);
    SerReset (ser_output_refnum, stop10|noParity|data8|baud9600);
    /* (what does this do?) */
    {
      CntrlParam cb;
      struct SerShk *handshake;
      
      cb.ioCRefNum = ser_output_refnum;
      cb.csCode = 14;
      handshake = (struct SerShk *) &cb.csParam[0];
      handshake->fXOn = 0;
      handshake->fCTS = 0;
      handshake->xOn = 0;
      handshake->xOff = 0;
      handshake->errs = 0;
      handshake->evts = 0;
      handshake->fInX = 0;
      handshake->fDTR = 0;
      err = PBControl ((ParmBlkPtr) &cb, 0);
    }
}

static void
low_serial_send(int id, char *buf)
{
    OSErr err;
    IOParam pb;

    pb.ioRefNum = ser_output_refnum;
    pb.ioBuffer = (Ptr) buf;
    pb.ioReqCount = strlen(buf);
    err = PBWrite((ParmBlkPtr) &pb, 0);
}

static int
low_serial_readchars(char *buf, int maxchars, int timeout)
{
    int status, n, n2;
    /* time_t */ unsigned long start_time, now;
    OSErr err;
    CntrlParam cb;
    IOParam pb;

    time (&start_time);

    while (1) {
      cb.ioCRefNum = ser_input_refnum;
      cb.csCode = 2;
      err = PBStatus((ParmBlkPtr) &cb, 0);
      if (err < 0)
        return FALSE;
      n = *((long *) &cb.csParam[0]);
      if (n > 0) {
          pb.ioRefNum = ser_input_refnum;
          pb.ioBuffer = (Ptr) buf;
          pb.ioReqCount = (n > 64 ? 64 : n);
          err = PBRead((ParmBlkPtr) &pb, 0);
          if (err < 0)
            return FALSE;
          n2 = pb.ioReqCount;
          buf[n2] = '\0';
          return TRUE;
      } else if (timeout == 0) {
          return FALSE;
      } else if (timeout == -1) {
          /* Go around again. */
      } else {
          time (&now);
          if (now > start_time + timeout) {
            Dprintf("%ul > %ul + %d\n", now, start_time, timeout);
            return FALSE /* timed out */;
          }
      }
    }
}

static void
close_serial_port()
{
    if (ser_input_refnum)
      CloseDriver(ser_input_refnum);
    if (ser_output_refnum)
      CloseDriver(ser_output_refnum);
}

NamesTableEntry names_table_entry;

int nbp_registered;

unsigned char atp_socket_number;

AddrBlock remote_addr;

static void
open_appletalk()
{
#ifndef __MWERKS__
    int i, numgotten;
    OSErr err;
    ATPParamBlock tmpATPPB;
    MPPParamBlock tmpMPPPB, tmpCancelMPPPB;
    NamesTableEntry lookup;
    char *namesbuffer;
    char *bigbuffer;
    EntityName entityname;
    AddrBlock entityaddr;

    if (IsMPPOpen == false) {
      err = MPPOpen();
      /* (should check result) */
    }

    tmpMPPPB.SETSELF.newSelfFlag = true;
    err = PSetSelfSend(&tmpMPPPB, false);
    /* (should check result) */

    /* (should collect our own network address?) */

    tmpATPPB.ATP.atpSocket = 0;
    tmpATPPB.ATP.addrBlock.aNet = 0;
    tmpATPPB.ATP.addrBlock.aNode = 0;
    tmpATPPB.ATP.addrBlock.aSocket = 0;
    err = POpenATPSkt(&tmpATPPB, false);
    /* (should check result) */

    NBPSetNTE(&names_table_entry, "\pStan", "\pXconq", "\p*", 64);

    tmpMPPPB.NBP.ioCompletion = nil;
    tmpMPPPB.NBP.interval = 0x0F;
    tmpMPPPB.NBP.count = 0x03;
#if 0
    tmpMPPPB.NBP.nbpPtrs.entityPtr = &names_table_entry;
#else
    tmpMPPPB.NBP.NBPPtrs.entityPtr = &names_table_entry;
#endif
    tmpMPPPB.NBP.parm.verifyFlag = true;
      
    err = PRegisterName(&tmpMPPPB, true);
    /* (should check result) */

    {
      short itemHit;
      EventRecord theEvent;
      Point mouse;
      extern void get_global_mouse(Point *mouse);

      do 
        {
            itemHit = 0;
            
            if (GetNextEvent(everyEvent,&theEvent) == true && IsDialogEvent(&theEvent) == true)
            {
                  
                get_global_mouse(&mouse);
                if (mouse.v == 0 && mouse.h == 0)
                  itemHit = 1;      
                  
                else
                  {
                    itemHit = 0;
                  }
            }
            
        } while (itemHit != 1 && tmpMPPPB.NBP.ioResult == 1);

      if (itemHit == 1)
        {
            tmpCancelMPPPB.NBPKILL.nKillQEl = (Ptr) &tmpMPPPB;
            
            PKillNBP(&tmpCancelMPPPB, false);
        } else
          nbp_registered = TRUE;
    }

    bigbuffer = xmalloc(10000);
    namesbuffer = xmalloc(250 * 33);

    NBPSetEntity((Ptr)&lookup.nt.entityData, "\p=", "\pXconq", "\p*");

    tmpMPPPB.NBP.ioCompletion = nil;
    tmpMPPPB.NBP.interval = 3;
    tmpMPPPB.NBP.count = 3;
    tmpMPPPB.NBPentityPtr = &lookup.nt.entityData;
    tmpMPPPB.NBPretBuffSize = 10000;
    tmpMPPPB.NBPretBuffPtr = bigbuffer;
    tmpMPPPB.NBPmaxToGet = 1000 / sizeof(NTElement);

    err = PLookupName(&tmpMPPPB, false);

    numgotten = tmpMPPPB.NBP.parm.Lookup.numGotten;
    if (numgotten > 0) {
#if 0
      master_rid = 1;
      if (willhost) {
          my_rid = 1;
      } else {
          my_rid = 2;
      }
      numremotes = 1;
#endif
      /* (should use this loop to get actual number of remotes) */
      for (i = 0; i < numgotten; ++i) {
          err = NBPExtract(namesbuffer, numgotten, i + 1, &entityname, &remote_addr); 
      }
    }

    /* (should release big buffers) */

    /* Open an ATP socket. */

    tmpATPPB.ATP.atpSocket = 0;
    tmpATPPB.ATP.addrBlock.aNet = 0;
    tmpATPPB.ATP.addrBlock.aNode = 0;
    tmpATPPB.ATP.addrBlock.aSocket = 0;

    err = POpenATPSkt(&tmpATPPB, false);

    atp_socket_number = tmpATPPB.ATP.atpSocket;
#endif /* __MWERKS__ */
}

static int
low_appletalk_receive(int *idp, char *buf, int maxchars, int timeout)
{
#ifndef __MWERKS__
    int status, n;
    /* time_t */ unsigned long start_time, now;
    OSErr err;
    int numbds;
    char atprequestbuf[256];
    BDSType bds;
    ATPParamBlock requestATPPB, replyATPPB;

    time (&start_time);

    while (1) {
      requestATPPB.ATP.ioCompletion = nil;
      requestATPPB.ATP.atpSocket = atp_socket_number;
      requestATPPB.ATP.reqLength = maxchars;
      requestATPPB.ATP.reqPointer = buf;

      err = PGetRequest(&requestATPPB, false);

      numbds = BuildBDS("OK", &bds, 256);

      replyATPPB.ATP.ioCompletion = nil;
      replyATPPB.ATP.atpFlags = atpEOMvalue;
      replyATPPB.ATP.atpSocket = atp_socket_number;
      replyATPPB.ATP.addrBlock = requestATPPB.ATP.addrBlock;
      replyATPPB.ATP.reqLength = strlen(buf) + 1;
      replyATPPB.ATP.bdsPointer = &bds;
      replyATPPB.OTH1.u0.numOfBuffs = 1;
      replyATPPB.OTH2.bdsSize = 256;
      replyATPPB.OTH2.transID = requestATPPB.ATP.reqTID;

      err = PSendResponse(&replyATPPB, false);

      n = requestATPPB.ATP.reqLength;
      if (n > 0) {
          buf[n] = '\0';
          return TRUE;
      } else if (timeout == 0) {
          return FALSE;
      } else if (timeout == -1) {
          /* Go around again. */
      } else {
          time (&now);
          if (now > start_time + timeout) {
            Dprintf("%ul > %ul + %d\n", now, start_time, timeout);
            return FALSE /* timed out */;
          }
      }
    }
#else
    return 0;
#endif /* __MWERKS__ */
}

static void
low_appletalk_send(int id, char *buf)
{
#ifndef __MWERKS__
    int numbds;
    char atpresponsebuf[256];
    OSErr err;
    BDSType bds;
    ATPParamBlock tmpATPPB;

    numbds = BuildBDS(atpresponsebuf, &bds, 256);

    tmpATPPB.ATP.ioCompletion = nil;
    tmpATPPB.ATP.atpFlags = 0;

    tmpATPPB.ATP.atpSocket = atp_socket_number;
    tmpATPPB.ATP.addrBlock.aNet = remote_addr.aNet;
    tmpATPPB.ATP.addrBlock.aNode = remote_addr.aNode;
    tmpATPPB.ATP.addrBlock.aSocket = remote_addr.aSocket;
    tmpATPPB.ATP.reqLength = strlen(buf) + 1;
    tmpATPPB.ATP.reqPointer = buf;
    tmpATPPB.ATP.bdsPointer = &bds;
    tmpATPPB.SREQ.timeOutVal = 10;
    tmpATPPB.SREQ.retryCount = 3;

    err = PSendRequest(&tmpATPPB, false);
#endif /* __MWERKS __ */
}

static void
close_appletalk()
{
#ifndef __MWERKS__
    OSErr err;
    ATPParamBlock tmpATPPB;
    MPPParamBlock tmpMPPPB;

    tmpATPPB.ATP.atpSocket = atp_socket_number;

    err = PCloseATPSkt(&tmpATPPB, false);

    if (nbp_registered) {
      tmpMPPPB.NBP.NBPPtrs.entityPtr = (Ptr) &names_table_entry.nt.entityData;
            
      err = PRemoveName(&tmpMPPPB, false);
      nbp_registered = FALSE;
    }
#endif /* __MWERKS __ */
}

Generated by  Doxygen 1.6.0   Back to index