/*
 * pdev.c
 *
 * set printer preferences device name/unit
 * with command line, GUI and WB tooltypes usage options.
 *
 * Timo Rossi, 1993
 *
 *
 * Compiles with SAS/C 6.x
 *
 */

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <libraries/iffparse.h>
#include <dos/dos.h>
#include <graphics/gfxbase.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <prefs/prefhdr.h>
#include <prefs/printertxt.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/iffparse_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/icon_protos.h>

#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

/*
 * SAS/C specific includes.
 *
 */
#ifdef __SASC
#include <pragmas/exec_sysbase_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/iffparse_pragmas.h>
#include <pragmas/gadtools_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/icon_pragmas.h>

/* these two cause SAS/C to produce a smaller executable,
 * but you can't use stdio.
 */
#define exit _XCEXIT
void _MemCleanup(void) {}
#endif

/*
 * version string
 */
char Version_String[] = "\0$VER: pdev 0.4 (9.8.93)";

#define PREF_FILENAME "env:sys/printer.prefs"
#define PREF_SAVE_FILENAME "envarc:sys/printer.prefs"
#define DEVICE_EXT ".device"

#define PROG_TEMPLATE "DEVICE,UNIT/N,FLAGS/N/K,NODEV/S,SAVE/S,PUBSCREEN/K"
/* RDArgs argument array index values */
enum {
	DEVICE_ARG = 0,
	UNIT_ARG,
	FLAGS_ARG,
	NODEV_ARG,
	SAVE_ARG,
	PUBSCREEN_ARG,
	NUM_ARGS
     };

BOOL GUI;

/* Gadget IDs */
enum {
	DEVICE_ID = 0x111,
	UNIT_ID,
	FLAGS_ID,
	CANCEL_ID,
	USE_ID,
	SAVE_ID
     };

/*
 * WBenchMsg is the workbench startup message. It is defined
 * in SAS/C startup code. Other compilers may use different
 * ways to access it.
 *
 */
extern struct WBStartup *WBenchMsg;

struct RDArgs *ProgArgs = NULL;

extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;

/*
 * Library bases
 */
struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library *GadToolsBase;
struct Library *IFFParseBase = NULL;
struct Library *IconBase = NULL;

/*
 * This program's (or project's) icon. Used to find tooltypes.
 */
struct DiskObject *IconObject = NULL;

struct IFFHandle *IFFHandle = NULL;

struct Gadget *DeviceGad, *UnitGad, *FlagsGad;

struct Window *Window = NULL;
void *VisualInfo = NULL;

struct Gadget *ContextGadget = NULL;
struct Gadget *glist;
BOOL GadgetsAdded = FALSE;

UBYTE *PubScName = NULL;

struct PrefHeader pheader;
struct PrinterTxtPrefs ptprefs;
struct PrinterUnitPrefs puprefs;

void cleanup(void)
{
  ULONG stream;

  if(IFFHandle)
     {
	stream = IFFHandle->iff_Stream;
	FreeIFF(IFFHandle);
	if(stream) Close((BPTR)stream);
     }
  if(ContextGadget)
     {
	if(GadgetsAdded) RemoveGList(Window, ContextGadget, ~0);
	FreeGadgets(ContextGadget);
     }
  if(Window) CloseWindow(Window);
  if(VisualInfo) FreeVisualInfo(VisualInfo);
  if(IconObject) FreeDiskObject(IconObject);
  if(IconBase) CloseLibrary(IconBase);
  if(IFFParseBase) CloseLibrary(IFFParseBase);
  if(GadToolsBase) CloseLibrary(GadToolsBase);
  if(GfxBase) CloseLibrary((struct Library *)GfxBase);
  if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
  if(ProgArgs) FreeArgs(ProgArgs);
}

void errexit(char *fmt , ...)
{
  static struct EasyStruct es;
  va_list args;

  va_start(args, fmt);
  if(IntuitionBase && (GUI || WBenchMsg))
     {
	es.es_StructSize = sizeof(es);
	es.es_Flags = 0;
	es.es_Title = "pdev error";
	es.es_TextFormat = fmt;
	es.es_GadgetFormat = "Ok";
	EasyRequestArgs(Window, &es, NULL, args);
     }
  else
     {
	VPrintf(fmt, (LONG *)args);
	PutStr("\n");
     }
  va_end(args);
  exit(RETURN_ERROR);
}

void InitThings(void)
{
  if((IntuitionBase = (struct IntuitionBase *)
     OpenLibrary("intuition.library", 37)) == NULL ||
     (GfxBase = (struct GfxBase *)
     OpenLibrary("graphics.library", 37)) == NULL ||
     (GadToolsBase = OpenLibrary("gadtools.library", 37)) == NULL)
	errexit("No Gfx/Intuition/Gadtools");

  if((IFFParseBase = OpenLibrary("iffparse.library", 0)) == NULL)
	errexit("Can't open iffparse.library");

  if((IFFHandle = AllocIFF()) == NULL)
	errexit("Out of memory (AllocIFF)");
}

void OpenGUI(void)
{
  static WORD ZoomSize[4];
  struct Screen *Screen;
  struct Gadget *gg;
  int FontWidth, FontHeight;

  static struct TextAttr TxAttr;

  static struct NewGadget NG;

  if((Screen = LockPubScreen(PubScName)) == NULL)
	errexit("Can't find public screen\n%s", PubScName);

  TxAttr.ta_Name = GfxBase->DefaultFont->tf_Message.mn_Node.ln_Name;
  TxAttr.ta_YSize = GfxBase->DefaultFont->tf_YSize;
  TxAttr.ta_Style = GfxBase->DefaultFont->tf_Style;
  TxAttr.ta_Flags = GfxBase->DefaultFont->tf_Flags;

  FontWidth = GfxBase->DefaultFont->tf_XSize;
  FontHeight = GfxBase->DefaultFont->tf_YSize;

  if((VisualInfo = GetVisualInfo(Screen, TAG_DONE)) == NULL)
    {
	UnlockPubScreen(NULL, Screen);
	errexit("Can't get VisualInfo");
    }

  ZoomSize[0] = 30 - Screen->LeftEdge;
  ZoomSize[1] = 15 - Screen->TopEdge;
  ZoomSize[2] = 220;
  ZoomSize[3] = Screen->BarHeight + 1;

  Window = OpenWindowTags(NULL,
	WA_Left, 30 - Screen->LeftEdge,
	WA_Top, 15 - Screen->TopEdge,
	WA_InnerWidth, (300 * FontWidth / 8),
	WA_InnerHeight, (105 * FontHeight / 8),
	WA_AutoAdjust, TRUE,
	WA_DragBar, TRUE,
	WA_DepthGadget, TRUE,
	WA_CloseGadget, TRUE,
	WA_Zoom, ZoomSize,
	WA_Activate, TRUE,
	WA_SimpleRefresh, TRUE,
	WA_RMBTrap, TRUE,
	WA_PubScreen, Screen,
	WA_Title, "Printer Device/Unit",
	WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW
		| IDCMP_VANILLAKEY | STRINGIDCMP | INTEGERIDCMP | BUTTONIDCMP,
	TAG_DONE);

  UnlockPubScreen(NULL, Screen);

  if(Window == NULL) errexit("Can't open window");

  if((ContextGadget = CreateContext(&glist)) == NULL)
	errexit("Can't create context gadget");

  NG.ng_TextAttr = &TxAttr;
  NG.ng_VisualInfo = VisualInfo;

  NG.ng_LeftEdge = (80 * FontWidth / 8) + Window->BorderLeft;
  NG.ng_TopEdge = (10 * FontHeight / 8) + Window->BorderTop;
  NG.ng_Width = (200 * FontWidth / 8);
  NG.ng_Height = (14 * FontHeight / 8);
  NG.ng_GadgetText = "Device";
  NG.ng_GadgetID = DEVICE_ID;
  NG.ng_Flags = PLACETEXT_LEFT;

  gg = CreateGadget(STRING_KIND, glist, &NG,
	GTST_MaxChars, DEVICENAMESIZE,
	TAG_DONE);
  if(gg) glist = gg;
  else errexit("Can't create gadget");
  DeviceGad = gg;

  NG.ng_TopEdge = (35 * FontHeight / 8) + Window->BorderTop;
  NG.ng_Width = (65 * FontWidth / 8);
  NG.ng_GadgetText = "Unit";
  NG.ng_GadgetID = UNIT_ID;

  gg = CreateGadget(INTEGER_KIND, glist, &NG,
	TAG_DONE);
  if(gg) glist = gg;
  else errexit("Can't create gadget");
  UnitGad = gg;

  NG.ng_TopEdge = (60 * FontHeight / 8) + Window->BorderTop;
  NG.ng_GadgetText = "Flags";
  NG.ng_GadgetID = FLAGS_ID;

  gg = CreateGadget(INTEGER_KIND, glist, &NG,
	TAG_DONE);
  if(gg) glist = gg;
  else errexit("Can't create gadget");
  FlagsGad = gg;

  NG.ng_LeftEdge = (10 * FontWidth / 8) + Window->BorderLeft;
  NG.ng_TopEdge = Window->Height - (20 * FontHeight / 8);
  NG.ng_Width = (80 * FontWidth / 8);
  NG.ng_Height = (14 * FontHeight / 8);
  NG.ng_GadgetText = "_Save";
  NG.ng_GadgetID = SAVE_ID;
  NG.ng_Flags = PLACETEXT_IN;

  gg = CreateGadget(BUTTON_KIND, glist, &NG,
	GT_Underscore, '_',
	TAG_DONE);
  if(gg) glist = gg;
  else errexit("Can't create gadget");

  NG.ng_LeftEdge = (110 * FontWidth / 8) + Window->BorderLeft;
  NG.ng_GadgetText = "_Use";
  NG.ng_GadgetID = USE_ID;

  gg = CreateGadget(BUTTON_KIND, glist, &NG,
	GT_Underscore, '_',
	TAG_DONE);
  if(gg) glist = gg;
  else errexit("Can't create use gadget");

  NG.ng_LeftEdge = (210 * FontWidth / 8) + Window->BorderLeft;
  NG.ng_GadgetText = "_Cancel";
  NG.ng_GadgetID = CANCEL_ID;

  gg = CreateGadget(BUTTON_KIND, glist, &NG,
	GT_Underscore, '_',
	TAG_DONE);
  if(gg) glist = gg;
  else errexit("Can't create gadget");

  AddGList(Window, ContextGadget, ~0, ~0, NULL);
  GadgetsAdded = TRUE;
  RefreshGadgets(ContextGadget, Window, NULL);
  GT_RefreshWindow(Window, NULL);
}

static UBYTE errbuf[100];

UBYTE *iff_errstr(int err)
{
  UBYTE *errstr;

  switch(err)
    {
      case IFFERR_EOF:
	errstr = "IFFParse: End of file";
	break;

      case IFFERR_NOMEM:
	errstr = "Out of memory (iffparse)";
	break;

      case IFFERR_READ:
	errstr = "Read error (iffparse)";
	break;

      case IFFERR_WRITE:
	errstr = "Write error (iffparse)";
	break;

      case IFFERR_SEEK:
	errstr = "Seek error (iffparse)";
	break;

      case IFFERR_MANGLED:
      case IFFERR_SYNTAX:
	errstr = "Corrupt IFF file";
	break;

      case IFFERR_NOTIFF:
	errstr = "Not an IFF file";
	break;

      default:
	errstr = "Unknown iffparse error";
	break;
    }

  return errstr;
}

void ReadPrinterPrefs(char *fname)
{
  int err;
  struct ContextNode *cn;
  BOOL HavePRHD	= FALSE, HavePTXT = FALSE, HavePUNT = FALSE;

  if((IFFHandle->iff_Stream =
     (ULONG)Open(fname, MODE_OLDFILE)) == NULL)
     {
	Fault(IoErr(), NULL, errbuf, sizeof(errbuf));
	errexit("Can't open %s\n%s", fname, errbuf);
     }

  InitIFFasDOS(IFFHandle);
  if(err = OpenIFF(IFFHandle, IFFF_READ))
	errexit("OpenIFF: %s", iff_errstr(err));

  while((err = ParseIFF(IFFHandle, IFFPARSE_STEP)) == 0 || err == IFFERR_EOC)
     {
	if(err == IFFERR_EOC || (cn = CurrentChunk(IFFHandle)) == NULL ||
	    cn->cn_Type != ID_PREF)
		continue;

	switch(cn->cn_ID)
	   {
	     case ID_PRHD:
		if(cn->cn_Size != sizeof(pheader))
			errexit("PRHD chunk wrong size");
		if((err = ReadChunkBytes(IFFHandle, &pheader,
		    sizeof(pheader))) <= 0)
			errexit("PRHD read error %d", err);
		HavePRHD = TRUE;
		break;

	     case ID_PTXT:
		if(cn->cn_Size != sizeof(ptprefs))
			errexit("PTXT chunk wrong size");
		if((err = ReadChunkBytes(IFFHandle, &ptprefs,
		    sizeof(ptprefs))) <= 0)
			errexit("PTXT read error %d", err);
		HavePTXT = TRUE;
		break;

	     case ID_PUNT:
		if(cn->cn_Size != sizeof(puprefs))
			errexit("PUNT chunk wrong size");
		if((err = ReadChunkBytes(IFFHandle, &puprefs,
		    sizeof(puprefs))) <= 0)
			errexit("PUNT read error %d", err);
		HavePUNT = TRUE;
		break;
	   }
     }

  if(err != 0 && err != IFFERR_EOF)
	errexit("ParseIFF: %s", iff_errstr(err));

  if(!HavePRHD || !HavePTXT)
	errexit("Invalid/incomplete printer preferences file");

  if(!HavePUNT)
	PutStr("No PUNT chunk\n");

  CloseIFF(IFFHandle);
  Close((BPTR)IFFHandle->iff_Stream);
  IFFHandle->iff_Stream = 0;
}

void WritePrinterPrefs(char *fname)
{
  int err;

  if((IFFHandle->iff_Stream =
     (ULONG)Open(fname, MODE_NEWFILE)) == NULL)
     {
	Fault(IoErr(), NULL, errbuf, sizeof(errbuf));
	errexit("Can't open %s for writing\n%s", fname, errbuf);
     }

  InitIFFasDOS(IFFHandle);
  if(err = OpenIFF(IFFHandle, IFFF_WRITE))
	errexit("OpenIFF: %s", iff_errstr(err));

  if(err = PushChunk(IFFHandle, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN))
	errexit("PushChunk(FORM) failed, error %d", err);

  if(err = PushChunk(IFFHandle, ID_PREF, ID_PRHD, sizeof(pheader)))
	errexit("PushChunk(PRHD): %s", iff_errstr(err));
  if((err = WriteChunkBytes(IFFHandle, &pheader, sizeof(pheader))) < 0)
	errexit("PRHD Write error %d", err);
  if(err = PopChunk(IFFHandle))
	errexit("PopChunk: %s", iff_errstr(err));

  if(err = PushChunk(IFFHandle, ID_PREF, ID_PTXT, sizeof(ptprefs)))
	errexit("PushChunk(PREF): %s", iff_errstr(err));
  if((err = WriteChunkBytes(IFFHandle, &ptprefs, sizeof(ptprefs))) < 0)
	errexit("PTXT Write error %d", err);
  if(err = PopChunk(IFFHandle))
	errexit("PopChunk: %s", iff_errstr(err));

  if(err = PushChunk(IFFHandle, ID_PREF, ID_PUNT, sizeof(puprefs)))
	errexit("PushChunk(PUNT): %s", iff_errstr(err));
  if((err = WriteChunkBytes(IFFHandle, &puprefs, sizeof(puprefs))) < 0)
	errexit("PUNT Write error %d", err);
  if((err = PopChunk(IFFHandle)) || (err = PopChunk(IFFHandle)))
	errexit("PopChunk: %s", iff_errstr(err));

  CloseIFF(IFFHandle);
  Close((BPTR)IFFHandle->iff_Stream);
  IFFHandle->iff_Stream = 0;
}

void DoCmdLine(LONG ArgArray[])
{
  if(ArgArray[DEVICE_ARG] && ArgArray[NODEV_ARG])
	errexit("Invalid parameters");

  ReadPrinterPrefs(PREF_FILENAME);

  if(ArgArray[NODEV_ARG])
	memset(puprefs.pu_DeviceName, '\0', DEVICENAMESIZE);

  if(ArgArray[DEVICE_ARG])
     {
	int len;

	strncpy(puprefs.pu_DeviceName, (char *)ArgArray[DEVICE_ARG], DEVICENAMESIZE);
	len = strlen(puprefs.pu_DeviceName);
	if(len > strlen(DEVICE_EXT) &&
	   !strcmp(&puprefs.pu_DeviceName[len - strlen(DEVICE_EXT)], DEVICE_EXT))
	    {
		memset(&puprefs.pu_DeviceName[len-strlen(DEVICE_EXT)], 0,
			strlen(DEVICE_EXT));
		PutStr("`.device' extension removed\n");
	    }
     }

  if(ArgArray[UNIT_ARG])
	puprefs.pu_UnitNum = *((LONG *)ArgArray[UNIT_ARG]);

  if(ArgArray[FLAGS_ARG])
	puprefs.pu_OpenDeviceFlags = *((LONG *)ArgArray[FLAGS_ARG]);

  if(puprefs.pu_DeviceName[0])
	Printf("printer device name = '%s'", puprefs.pu_DeviceName);
  else PutStr("no device name");

  Printf(" -- unit number %ld, flags %ld\n",
	puprefs.pu_UnitNum, puprefs.pu_OpenDeviceFlags);

  if(ArgArray[DEVICE_ARG] || ArgArray[NODEV_ARG] ||
     ArgArray[UNIT_ARG] || ArgArray[FLAGS_ARG])
	WritePrinterPrefs(PREF_FILENAME);

  if(ArgArray[SAVE_ARG])
	WritePrinterPrefs(PREF_SAVE_FILENAME);
}

/*
 * Device name check function for GUI prefs editor
 * If the name contains a '.device' suffix, the suffix is removed
 *
 */
void CheckDevStr(void)
{
  int len;

  strncpy(puprefs.pu_DeviceName,
	((struct StringInfo *)DeviceGad->SpecialInfo)->Buffer,
	DEVICENAMESIZE);

  len = strlen(puprefs.pu_DeviceName);
  if(len > strlen(DEVICE_EXT) &&
     !strcmp(&puprefs.pu_DeviceName[len - strlen(DEVICE_EXT)], DEVICE_EXT))
	{
	    memset(&puprefs.pu_DeviceName[len-strlen(DEVICE_EXT)], 0,
		strlen(DEVICE_EXT));

	    GT_SetGadgetAttrs(DeviceGad, Window, NULL,
		GTST_String, puprefs.pu_DeviceName,
		TAG_DONE);
	}
}

/*
 * The GUI (graphical user interface)
 * printer device/unit preferences editor
 *
 */
void DoGUI(void)
{
  enum {
	 doLOOP = 1,
	 doUSE,
	 doSAVE,
	 doCANCEL,
       };

  short state = doLOOP;
  struct IntuiMessage *msg;

  GUI = TRUE;
  OpenGUI();

  ReadPrinterPrefs(PREF_FILENAME);

  GT_SetGadgetAttrs(DeviceGad, Window, NULL,
	GTST_String, puprefs.pu_DeviceName,
	TAG_DONE);

  GT_SetGadgetAttrs(UnitGad, Window, NULL,
	GTIN_Number, puprefs.pu_UnitNum,
	TAG_DONE);

  GT_SetGadgetAttrs(FlagsGad, Window, NULL,
	GTIN_Number, puprefs.pu_OpenDeviceFlags,
	TAG_DONE);

  while(state == doLOOP)
    {
	if(Wait((1 << Window->UserPort->mp_SigBit) | SIGBREAKF_CTRL_C)
	   & SIGBREAKF_CTRL_C)
		return;
	while(msg = GT_GetIMsg(Window->UserPort))
	   {
	      switch(msg->Class)
		{
		  case IDCMP_CLOSEWINDOW:
		    state = doCANCEL;
		    break;

		  case IDCMP_REFRESHWINDOW:
		    GT_BeginRefresh(Window);
		    GT_EndRefresh(Window, TRUE);
		    break;

		  case IDCMP_GADGETUP:
		    switch(((struct Gadget *)msg->IAddress)->GadgetID)
		      {
			case DEVICE_ID:
			  CheckDevStr();
			  break;

			case USE_ID:
			  state = doUSE;
			  break;

			case SAVE_ID:
			  state = doSAVE;
			  break;

			case CANCEL_ID:
			  state = doCANCEL;
			  break;
		      }
		    break;

		  case IDCMP_VANILLAKEY:
		    switch(msg->Code)
		      {
			case 's': case 'S':
			  state = doSAVE;
			  break;

			case 'u': case 'U':
			  state = doUSE;
			  break;

			case 'c': case 'C':
			case 0x1b: /* ESC */
			  state = doCANCEL;
			  break;

			/* Hmm.. is this legal? or is there another way to
			 * activate a GadTools string gadget?
			 */
			case '\r': /* Return/Enter */
			case '\t': /* TAB */
			  ActivateGadget(DeviceGad, Window, NULL);
			  break;
		      }
		    break;
		}

	      GT_ReplyIMsg(msg);
	   }
    }

  if(state == doSAVE || state == doUSE)
     {
	CheckDevStr();
	strncpy(puprefs.pu_DeviceName,
	    ((struct StringInfo *)DeviceGad->SpecialInfo)->Buffer,
		DEVICENAMESIZE);

	puprefs.pu_UnitNum =
		((struct StringInfo *)UnitGad->SpecialInfo)->LongInt;
	puprefs.pu_OpenDeviceFlags =
		((struct StringInfo *)FlagsGad->SpecialInfo)->LongInt;

	WritePrinterPrefs(PREF_FILENAME);

	if(state == doSAVE)
		WritePrinterPrefs(PREF_SAVE_FILENAME);
     }
}

/*
 * Set the printer device/unit preference settings according
 * to tooltypes. Optionally save the preferences.
 *
 */
void DoTT(UBYTE *devt, UBYTE *unitt, UBYTE *flagst, BOOL saveflag)
{
  int len;

  ReadPrinterPrefs(PREF_FILENAME);

  if(devt)
     {
	strncpy(puprefs.pu_DeviceName, devt, DEVICENAMESIZE);
	len = strlen(puprefs.pu_DeviceName);
	if(len > strlen(DEVICE_EXT) &&
	  !strcmp(&puprefs.pu_DeviceName[len - strlen(DEVICE_EXT)], DEVICE_EXT))
	    {
		memset(&puprefs.pu_DeviceName[len-strlen(DEVICE_EXT)], 0,
			strlen(DEVICE_EXT));
	    }
     }

  if(unitt && StrToLong(unitt, &puprefs.pu_UnitNum) < 1)
	errexit("Invalid number in UNIT tooltype");

  if(flagst && StrToLong(flagst, &puprefs.pu_OpenDeviceFlags) < 1)
	errexit("Invalid number in FLAGS tooltype");

  WritePrinterPrefs(PREF_FILENAME);
  if(saveflag) WritePrinterPrefs(PREF_SAVE_FILENAME);
}

/*
 * The main program
 *
 */
#ifdef __SASC
void __main(char *cmdline)
#else
main()
#endif
{
  static LONG ArgArray[NUM_ARGS];

  onexit(cleanup);

  if(DOSBase->dl_lib.lib_Version < 37)
     {
	Write(Output(), "This program requires 2.04 or later OS\n", 39);
	exit(RETURN_FAIL);
     }

  InitThings();

  if(WBenchMsg != NULL)
     {
	BPTR currdir;
	struct WBArg *wbarg;

	if((IconBase = OpenLibrary("icon.library", 0)) == NULL)
		errexit("Can't open icon.library");

	wbarg = &WBenchMsg->sm_ArgList[WBenchMsg->sm_NumArgs >= 2];
	currdir = CurrentDir(wbarg->wa_Lock);
	IconObject = GetDiskObject(wbarg->wa_Name);
	CurrentDir(currdir);
	if(IconObject != NULL)
	    {
		UBYTE *devt, *unitt, *flagst;
		BOOL uset, savet;

		PubScName = FindToolType(IconObject->do_ToolTypes, "PUBSCREEN");
		devt = FindToolType(IconObject->do_ToolTypes, "DEVICE");
		unitt = FindToolType(IconObject->do_ToolTypes, "UNIT");
		flagst = FindToolType(IconObject->do_ToolTypes, "FLAGS");
		uset = (FindToolType(IconObject->do_ToolTypes, "USE") != NULL);
		savet = (FindToolType(IconObject->do_ToolTypes, "SAVE") != NULL);

		if(uset && savet)
			errexit("Bad combination of tooltypes (USE & SAVE)");

		if(devt || unitt || flagst)
		    {
			if(uset || savet)
				DoTT(devt, unitt, flagst, savet);
			else errexit("USE or SAVE tooltype expected");
			exit(RETURN_OK);
		    }
	    }
	DoGUI();
     }
  else
     {
	if((ProgArgs = ReadArgs(PROG_TEMPLATE, ArgArray, NULL)) == NULL)
	     {
		PrintFault(IoErr(), "pdev");
		exit(RETURN_ERROR);
	     }
	PubScName = (UBYTE *)ArgArray[PUBSCREEN_ARG];

	if(!ArgArray[DEVICE_ARG] && !ArgArray[UNIT_ARG] && !ArgArray[FLAGS_ARG]
		&& !ArgArray[NODEV_ARG] && !ArgArray[SAVE_ARG])
			DoGUI();
	else DoCmdLine(ArgArray);
     }
  exit(RETURN_OK);
}
