/* * XCMDLaser * * XCMD for Term II, allowing the download of PostScript files to * an Apple Laser Writer. We are using some functions of the * Laser Writer : * * - a ^D must be sent at the end of each file * - the printer send a ^D when current job is * finished, and a new file can be processed * * To compile with DICE : * * dcc XCMDTools.o XCMDLaser.c -o XCMDLaser * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "XCMD.h" #include "XCMDtools.h" /* * DEFINE */ #define BUF_SIZE 80 #define BOX 50 #define TIMEOUT_LIMIT 180 /* in seconds */ /* * VARIABLES */ struct MsgPort *port = NULL; struct XCMD *XCMD = NULL; FILE *fp = NULL; const char PRINTER_EOF = '\x04'; const char INTERRUPT = '\x03'; const char STATUS_QUERY = '\x14'; struct FileRequester *FileRequester = NULL; struct AslBase *AslBase = NULL; struct Library *GadToolsBase = NULL; struct IntuitionBase *IntuitionBase = NULL; struct GadgetList *glist = NULL; struct Window *window = NULL; struct Screen *screen = NULL; void *vi = NULL; struct Gadget *GadName, *GadStop;; struct TextAttr Topaz80 = { "topaz.font",8,0,0 }; /* * PROTOS */ void End(char *); void DownloadFile(char *); void ExecuteXCMD(char *, void *, void *, void *); void InitIntuition(void); long FileSize(char *); void HandleIntuition(void); void UpdateBox(long,long); void exit(int); /* * MAIN */ int main(int argc, char *argv[]) { char buffer_name[256]; /* * Allocate and initialize ressources */ if(!FindPort("TERM")) End("I can't find Term II"); port = CreatePort("LASER",0); if(!port) End("I can't create my message port"); XCMD = CreateXCMD(port); if(!XCMD) End("I can't create the XCMD"); AslBase = OpenLibrary(AslName,36); if(!AslBase) End("I can't find library asl v36 or above"); struct FileRequester *FileRequester = AllocAslRequest(ASL_FileRequest,NULL); if(!FileRequester) End("I can't create a file requester"); InitIntuition(); /* * Get files and print them */ if(AslRequestTags(FileRequester,ASL_FuncFlags,FILF_MULTISELECT|FILF_PATGAD, ASL_Pattern,(ULONG)"#?", ASL_Hail,(ULONG)"Multiselect", TAG_DONE)) { int nb_files = FileRequester->rf_NumArgs; if(nb_files) { struct WBArg *wb_arg = FileRequester->rf_ArgList; while(nb_files--) { NameFromLock(wb_arg->wa_Lock,buffer_name,256); AddPart(buffer_name,wb_arg->wa_Name,256); DownloadFile(buffer_name); wb_arg++; } } else { if(FileRequester->rf_File[0] != '\0') { strcpy(buffer_name,FileRequester->rf_Dir); AddPart(buffer_name,FileRequester->rf_File,256); DownloadFile(buffer_name); } } } End("Done"); } /* * void End(char *message) * * End program and free ressources */ void End(char *message) { puts(message); if(XCMD) /* This to be sure to make Term II read the serial port */ { /* * We don't use ExecuteXCMD(), for in case of * error we'll be back here for an infinite loop */ XCMD->xcmd_Command = "serial_on"; if(SendXCMD(XCMD)) { WaitPort(port); GetMsg(port); } } if(fp) fclose(fp); if(XCMD) DeleteXCMD(XCMD); if(port) DeletePort(port); if(FileRequester) FreeAslRequest(FileRequester); if(AslBase) CloseLibrary(AslBase); if(window) { struct IntuiMessage *msg; while(msg = GT_GetIMsg(window->UserPort)) GT_ReplyIMsg(msg); CloseWindow(window); } if(vi) FreeVisualInfo(vi); if(glist) FreeGadgets(glist); if(screen) UnlockPubScreen(NULL,screen); if(GadToolsBase) CloseLibrary(GadToolsBase); if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase); exit(0); } /* * void DownloadFile(char *filename) * * Download the file whose name is filename */ void DownloadFile(char *filename) { unsigned char write_buffer[BUF_SIZE]; char intui_buffer[60]; long file_size = FileSize(filename); long size = 0; sprintf(intui_buffer,"Downloading %s (%d bytes)",FilePart(filename),file_size); GT_SetGadgetAttrs(GadName,window,NULL,GTTX_Text,intui_buffer,TAG_DONE); fp = fopen(filename,"r"); if(!fp) End("I can't open file"); char c; int i = 0; while((c=getc(fp)) != EOF) { write_buffer[i] = c; i++; if(i == BUF_SIZE) { ExecuteXCMD("xcmd_swrite",write_buffer,(void *)BUF_SIZE,NULL); size += BUF_SIZE; HandleIntuition(); UpdateBox(size,file_size); i = 0; } } if(i>0) ExecuteXCMD("xcmd_swrite",write_buffer,(void *)i,NULL); /* * We get sure Term II will read chars only when we * ask for it. */ ExecuteXCMD("serial_off",NULL,NULL,NULL); ExecuteXCMD("xcmd_swrite",&PRINTER_EOF,(void *)1,NULL); size+=i; UpdateBox(size,file_size); /* * Wait for a ^D. See time out value */ BOOL not_the_end = TRUE; while(not_the_end) { HandleIntuition(); int i; for(i=0; ixcmd_Args[15])>0) { if(eof == PRINTER_EOF) { not_the_end = FALSE; break; } } HandleIntuition(); } if(not_the_end) End("No answer from printer"); } ExecuteXCMD("serial_on",NULL,NULL,NULL); fclose(fp); fp = NULL; GT_SetGadgetAttrs(GadName,window,NULL,GTTX_Text,NULL,TAG_DONE); SetAPen(window->RPort,(UBYTE)0); RectFill(window->RPort,BOX+4,58,BOX+4+242,70); SetAPen(window->RPort,(UBYTE)3); } /* * void ExecuteXCMD() * * Execute an XCMD and wait for an answer. Quit in case of * error. */ void ExecuteXCMD(char *command, void *arg1, void *arg2, void *arg3) { if(!XCMD) End("No XCMD !"); XCMD->xcmd_Command = command; XCMD->xcmd_Args[0] = arg1; XCMD->xcmd_Args[1] = arg2; XCMD->xcmd_Args[2] = arg3; if(SendXCMD(XCMD)) { WaitPort(port); GetMsg(port); } else End("SendXCMD() failed"); } /* * void InitIntuition() * * Init intuition */ void InitIntuition() { ExecuteXCMD("xcmd_lock_request",NULL,NULL,NULL); screen = XCMD->xcmd_TermScreen; UnLock(XCMD->xcmd_TermDir); IntuitionBase = OpenLibrary("intuition.library",36); if(!IntuitionBase) End("No intuition.library v36 or above"); GadToolsBase = OpenLibrary("gadtools.library",36); if(!GadToolsBase) End("No gadtools.library v36 or above"); vi = GetVisualInfo(screen, TAG_DONE); if(!vi) End("I can't get visual info"); window = OpenWindowTags(NULL, WA_Top, 20, WA_Left, 15, WA_DragBar, TRUE, WA_DepthGadget, TRUE, WA_PubScreen, screen, WA_Width, 350, WA_Height, 120, WA_IDCMP, REFRESHWINDOW|TEXTIDCMP|BUTTONIDCMP, WA_Title, "Downloading PostScript files (v1.0)", WA_Activate, TRUE, TAG_DONE); if(!window) End("I can't open the window"); struct Gadget *gad = CreateContext(&glist); struct NewGadget ng; ng.ng_TextAttr = &Topaz80; ng.ng_VisualInfo = vi; ng.ng_LeftEdge = 10; ng.ng_TopEdge = 30; ng.ng_Width = 260; ng.ng_Height = 10; ng.ng_Flags = 0; ng.ng_GadgetText = NULL; gad = GadName = CreateGadget(TEXT_KIND,gad,&ng,TAG_DONE); ng.ng_TopEdge += 60; ng.ng_LeftEdge = 130; ng.ng_Height = 14; ng.ng_Width = 100; ng.ng_GadgetText = "STOP"; gad = GadStop = CreateGadget(BUTTON_KIND,gad,&ng,TAG_DONE); if(!gad) End("I can't create gadgets"); AddGList(window,glist,-1,-1,NULL); RefreshGList(glist,window,NULL,-1); GT_RefreshWindow(window,NULL); DrawBevelBox(window->RPort,BOX,55,250,20,GT_VisualInfo,vi,GTBB_Recessed,TRUE,TAG_DONE); } /* * void HandleIntuition() * * Handle Intuition events */ void HandleIntuition() { struct IntuiMessage *msg; BOOL stop = FALSE; while(msg = GT_GetIMsg(window->UserPort)) { ULONG class = msg->Class; struct Gadget *gadget = msg->IAddress; GT_ReplyIMsg(msg); switch(class) { case GADGETUP : if(gadget == GadStop) stop = TRUE; break; case REFRESHWINDOW : GT_BeginRefresh(window); GT_EndRefresh(window,TRUE); break; default: break; } } if(stop) { ExecuteXCMD("xcmd_swrite",&INTERRUPT,(void *)1,NULL); End("Stop by user"); } } /* * long FileSize(char *) * * Return size in bytes of a file */ long FileSize(char *filename) { BPTR lock = Lock(filename,ACCESS_READ); long size = 0; if(lock) { struct FileInfoBlock *fib = AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR|MEMF_PUBLIC); if(fib) { Examine(lock,fib); size = fib->fib_Size; FreeMem(fib,sizeof(struct FileInfoBlock)); } UnLock(lock); } return(size); } /* * void UpdateBox(long current, long size) * * Update the box reflecting current status of downloading. * current = nb of bytes already downloaded * size = nb of bytes to download */ void UpdateBox(long current, long size) { long width = (242 * current) / size; RectFill(window->RPort,BOX+4,58,BOX+width+4,70); }