/*
** $PROJECT: MultiPrint - print datatype objects
**
** $VER: MultiPrint.c 39.0 (07.08.95)
**
** by
**
** Stefan Ruppert , Windthorststraße 5 , 65439 Flörsheim , GERMANY
**
** (C) Copyright 1995
** All Rights Reserved !
**
** $HISTORY:
**
** 07.08.95 : 039.000 : initial beta version
**
*/

/*FS*/ /* $STARTDEFINE: "BumpRev defines"*/
#define VERSION  39
#define REVISION 0
#define DATE "7.8.95"
#define VERS "MultiPrint 39.0beta"
#define VSTRING "MultiPrint 39.0beta (7.8.95)\r\n"
#define VERSTAG "\0$VER: MultiPrint 39.0beta (7.8.95)"
/*FE*/ /* $ENDDEFINE:   */

/* ----------------------------- definitions ------------------------------ */

/*FS*/ /*"Definitions"*/

/* ------------------------------- includes ------------------------------- */

#define CATCOMP_BLOCK

#include "MultiPrint.h"

/* ------------------------------ prototypes ------------------------------ */

extern int MultiPrint(void);

static void SetError(struct GlobalData *gd,LONG err,STRPTR errobj);
static void NotifyUser(struct GlobalData *gd,LONG msgid,...);
static STRPTR GetString(struct GlobalData *gd,LONG id);
static BOOL FindMethod(Object *obj,ULONG method);

/* ------------------------------- strings -------------------------------- */

static const STRPTR multiprint       = "MultiPrint";
static const STRPTR version          = VERSTAG;

static const STRPTR datatypeslibrary = "datatypes.library";
static const STRPTR printerdevice    = "printer.device";

/*FE*/

/* ----------------------------- main program ----------------------------- */

/*FS*/ GetA4 int MultiPrint(void)
{
	LONG retval = RETURN_FAIL;
	struct GlobalData *gd;

	if((gd = Init()) != NULL)
	{
		struct Process *proc = (struct Process *) FindTask(NULL);
		struct RDArgs *args;
		STRPTR errobj = multiprint;

		if(proc->pr_CLI == NULL)
		{
			/* workbench start not supported */
			struct Message *msg;
			WaitPort(&proc->pr_MsgPort);
			msg = GetMsg(&proc->pr_MsgPort);
			Forbid();
			ReplyMsg(msg);
			retval = RETURN_ERROR;
		} else if(!(DOSBase = OpenLibrary("dos.library",39)))
		{
			retval = RETURN_FAIL;
		} else
		{
			retval = RETURN_OK;

			if(!(DataTypesBase = OpenLibrary(datatypeslibrary,39)))
				SetError(gd,ERROR_OBJECT_NOT_FOUND,datatypeslibrary);
			else
			{
				IntuitionBase = OpenLibrary("intuition.library",39);
				UtilityBase   = OpenLibrary("utility.library",39);
				IconBase      = OpenLibrary("icon.library",39);
				if((LocaleBase    = OpenLibrary("locale.library",38)))
					gd->gd_Catalog = OpenCatalog(NULL,"multiprint.catalog",
														  OC_BuiltInLanguage,"english",
														  TAG_DONE);

				if((args = ReadArgs(TEMPLATE,(LONG *) &gd->gd_Para,NULL)) != NULL)
				{
					STRPTR *files = gd->gd_Para.td_Files;
					Object *obj;

					/* printing initialization */
					if(!(gd->gd_PrintPort = CreateMsgPort()))
						SetError(gd,ERROR_NO_FREE_STORE,multiprint);
					else if(!(gd->gd_PrintIO = CreateIORequest(gd->gd_PrintPort,sizeof(union printerIO))))
						SetError(gd,ERROR_NO_FREE_STORE,multiprint);
					else if(!(OpenDevice(printerdevice,0,(struct IORequest *) gd->gd_PrintIO,0) == 0))
						SetError(gd,ERROR_OBJECT_NOT_FOUND,printerdevice);
					else
					{
						/* simulate a GadgetInfo structure */
						if((gd->gd_GInfo.gi_Screen = LockPubScreen(NULL)))
						{
							gd->gd_GInfo.gi_DrInfo = GetScreenDrawInfo(gd->gd_GInfo.gi_Screen);
						}

						gd->gd_PrintMsg.MethodID     = DTM_PRINT;
						gd->gd_PrintMsg.dtp_GInfo    = &gd->gd_GInfo;
						gd->gd_PrintMsg.dtp_PIO      = gd->gd_PrintIO;
						gd->gd_PrintMsg.dtp_AttrList = NULL;

						while(*files)
						{
							/* open the object */
							if((obj = NewDTObjectA(*files,NULL)))
							{
								struct DataType *dt;

								/* determine the datatype */
								if(GetAttr(DTA_DataType,obj,(ULONG *) &dt) == 1)
								{
									/* set here datatype specific printer prefs, so that we can print
									 * c source for example with 136 chars per line and normal text with
									 * 80 chars per line .
									 */
								}

								/* supports the object printing ? */
								if(FindMethod(obj,DTM_PRINT))
								{
									LONG rc;
									ULONG proc;

									/* layout the object */
									DoMethod(obj,GM_LAYOUT,&gd->gd_GInfo,1);

									/* just wait until the layout process has finished */
									while(GetDTAttrs(obj,DTA_LayoutProc,&proc,TAG_DONE) == 1 && proc)
										Delay(25);

									NotifyUser(gd,MSG_PRINTING_FILE,*files);

									/* now print the object */
									rc = DoMethodA(obj,(Msg) &gd->gd_PrintMsg);

									/* notify the user, that the printing is done or has been canceled */
									NotifyUser(gd,PRERR_NOERR + rc);
								} else
								{
									/* object doesn't support printing */
									NotifyUser(gd,MSG_NO_PRINTING_SUPPORTED,(LONG) *files);
								}
								/* delete this object */
								DisposeDTObject(obj);
							} else if(IoErr() != 0)
							{
								NotifyUser(gd,IoErr(),*files);
								SetIoErr(0);
							}

							files++;
						}

						if(gd->gd_GInfo.gi_Screen)
						{
							if(gd->gd_GInfo.gi_DrInfo)
								FreeScreenDrawInfo(gd->gd_GInfo.gi_Screen,gd->gd_GInfo.gi_DrInfo);

							UnlockPubScreen(NULL,gd->gd_GInfo.gi_Screen);
						}

						CloseDevice((struct IORequest *) gd->gd_PrintIO);
					}

					if(gd->gd_PrintIO)
						DeleteIORequest(gd->gd_PrintIO);

					if(gd->gd_PrintPort)
						DeleteMsgPort(gd->gd_PrintPort);

					FreeArgs(args);
				}

				if(LocaleBase)
				{
					if(gd->gd_Catalog)
						CloseCatalog(gd->gd_Catalog);
					CloseLibrary(LocaleBase);
				}

				CloseLibrary(IntuitionBase);
				CloseLibrary(UtilityBase);
				CloseLibrary(IconBase);
				CloseLibrary(DataTypesBase);
			}

			/* an error occured, so get the object, which caused that error */
			if(gd->gd_ErrorObject != NULL)
				errobj = gd->gd_ErrorObject;
		}

		if(DOSBase)
		{
			if(IoErr())
			{
				PrintFault(IoErr(),errobj);

				retval = RETURN_ERROR;
			}
			CloseLibrary(DOSBase);
		}

		Free(gd);
	}

	return(retval);
}
/*FE*/

/*FS*/ static STRPTR GetString(struct GlobalData *gd,LONG id)
{
	LONG   *l;
	UWORD  *w;
	STRPTR  builtIn;

	l = (LONG *)CatCompBlock;

	while (*l != id)
	{
		w = (UWORD *)((ULONG)l + 4);
		l = (LONG *)((ULONG)l + (ULONG)*w + 6);
	}
	builtIn = (STRPTR)((ULONG)l + 6);

	if(LocaleBase)
		return(GetCatalogStr((struct Catalog *) gd->gd_Catalog,id,builtIn));

	return(builtIn);

}
/*FE*/
/*FS*/ static void SetError(struct GlobalData *gd,LONG err,STRPTR errobj)
{
	SetIoErr(err);
	gd->gd_ErrorObject = errobj;
}
/*FE*/
/*FS*/ static void NotifyUser(struct GlobalData *gd,LONG msgid,...)
{
	if(!gd->gd_Para.td_Quiet)
	{
		va_list ap;
		STRPTR msg;

		va_start(ap,msgid);

		msg = gd->gd_Buffer;
		if(msgid >= 2000 && msgid < 3000)
			sprintf(gd->gd_Buffer,"%s: %s",multiprint,GetDTString(msgid));
		else if(msgid < 999)
			Fault(msgid,multiprint,msg,BUFFER_SIZE-1);
		else
			msg = GetString(gd,msgid);

		VPrintf(msg,ap);
		Flush(Output());

		va_end(ap);
	}
}
/*FE*/

/*FS*/ static BOOL FindMethod(Object *obj,ULONG method)
{
	ULONG *methods;
	BOOL retval = FALSE;

	if(DoMethod(obj,OM_GET,DTA_Methods,&methods))
	{
		while(*methods != ~0 && *methods != method)
			methods++;

		retval = (*methods == method);
	}

	return(retval);
}
/*FE*/

