home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright March 2001 J.v.d.Loo
-
- Treat this source code and the load file based on this source as Freeware - I would say Public
- Domain when this wouldn't give other people the right to add their copyright signs - which among
- other things can mean that the files Dump and Dump.c cannot be used freely...
-
- Start over:
- This file is not meant as lesson how to use the "printer device" but as an example how to use
- the (poor) DAC interface of BareED.
-
- Note: Any DAC-application will be started from BareED!
- A DAC-application will get a normal Workbench-start-up-message with additional
- information and functions that it may use.
- A DAC-aaplication may be written as base-relative (small code/data) or as large
- code/data model - it doesn't matter. The base register A4 of your program is remembered
- and restored by BareED!
- -> NOTE: Traditionally register A5 is used by the E-compiler - but currently BareED does
- not care about it - sorry.
- If a CallBack-Hook function of a DAC-application is called back you have to restore on
- exit all registers to their initial state, except D0-D1, A0-A1, A4.
-
- Note well: BareED is locked, better said: protected against modifications from the
- outside (non-DAC-applications), which means that the archive cannot be gone
- or changed when there is still at least one DAC-application alive -
- exception: a marked block!!! But the addresses of BlockStart and BlockEnd
- are still valid although the user could have already dismarked this block!
-
- Additional note:
- I have used standard Bitplanes and Bitmaps in this example although a 3rd
- party graphic board software could be running and therewith non-standard
- Bitplanes and Bitmaps (when used) would be more effective. But this requires
- on OS 3.0 and 3.1 a patched "printer.device". As far as I know the OSs 3.5
- and 3.9 support non-standard Bitmaps native.
-
- Used printer by author:
- Since I found no "printer driver" for my Canon BJC 2000 printer, I've freed
- from dust my old Epson LQ 400 printer and used it. Because the EpsonQ driver
- does not compute page sizes correctly (2804 dots in horizontal and 0 dots in
- vertical direction) I wrote a new "printer driver" called EpsonLQ that fixes
- these and other bugs (now it supports also the Euro-sign). Since the Epson
- LQ 400 printer has only 180 dpi in vertical direction, the result of Dump is
- poor. Perhaps with a better printer (device ?) the result of Dump is better.
-
- Help needed:
- If you know how to apply "anti-alias" to a given font (or how to render a
- font so that a "anti-alias" text can be performed) give me a hint. If you
- already managed to complete an useable routine please send it to me for free
- (email me in this case: Joergloo@aol.com).
-
- Fixed bug in header (LocaleBase set up as STRUCT Library* instead of STRUCT LocalBase*).
- Fixed crash that might occur when Paused and right after Abandoned printout (now use of CMD_FLUSH
- instead of AbortIO() ).
- Modified layout of strings where now no Compiler can grumble about unknow escape sequences.
- Adapted this source to GNU-C - used this commandline:
- > gcc -s -fbaserel -m68020 -O2 -fstrength-reduce -msmall-code -w -noixemul Dump.c
- */
-
-
- #include <exec/memory.h>
- #include <exec/libraries.h>
- #include <exec/ports.h>
-
- #include <dos/dos.h>
-
- #include <intuition/intuition.h>
- #include <intuition/screens.h>
- #include <intuition/preferences.h>
-
- #include <graphics/gfxbase.h>
- #include <graphics/gfx.h>
- #include <graphics/displayinfo.h>
- #include <graphics/rastport.h>
- #include <graphics/text.h>
-
- #include <libraries/locale.h>
-
- #include <workbench/startup.h>
-
- #include <devices/printer.h>
- #include <devices/prtbase.h>
-
- #include <devices/printer.h>
- #include <devices/prtbase.h>
-
- #include <clib/exec_protos.h>
- #include <clib/graphics_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/locale_protos.h>
- #include <clib/alib_protos.h>
- #include <clib/alib_stdio_protos.h>
-
- #if !defined(__MAXON__) && !defined(__STORM__)
- #include <proto/exec.h>
- #include <proto/graphics.h>
- #include <proto/intuition.h>
- #include <proto/gadtools.h>
- #include <proto/locale.h>
- #else
- #include <pragma/exec_lib.h>
- #include <pragma/graphics_lib.h>
- #include <pragma/intuition_lib.h>
- #include <pragma/gadtools_lib.h>
- #include <pragma/locale_lib.h>
- #endif
-
- #include <string.h>
-
-
- #if defined(__MAXON__) || defined(__STORM__) /* ... enable Workbench start */
- struct WBStartup *WBenchMsg = NULL; /* Variable */
- #if defined(__MAXON__)
- extern void wbparse( struct WBStartup *);
- #endif
- void wbmain( struct WBStartup *ws) /* This is called if we're running from WB */
- {
- WBenchMsg = ws; /* Remember message */
- #if defined(__MAXON__)
- wbparse( ws); /* Parse WBench arguments (argv[0....])*/
- #endif
- }
- #else
- #if defined(__GNUC__)
- extern struct WBStartup *_WBenchMsg;
- #define WBenchMsg _WBenchMsg
- #else
- extern struct WBStartup *WBenchMsg;
- #endif
- #endif
-
- /* Macro by G. Nikl */
- #if defined(__GNUC__)
- #define ASM
- #define REG(reg,arg) arg __asm(#reg)
- #else
- #define REG(reg,arg) register __##reg arg
- #endif
-
- #if defined(__MAXON__)
- #define ASM
- #define __saveds
- #endif
-
- #if defined(__STORM__)
- #define ASM
- #endif
-
-
- unsigned char VerStr[] = "$VER: DAC_Dump 21.13 (17-Apr-01)";
-
-
- struct ProgressBar /* Don't use other items than this one of the ProgressBar... */
- {
- struct Window *pb_Window;
- }; /* Don't rely on this end... */
-
-
- struct PseudoMsg
- {
- struct WBStartup pm_Startup; /* Only readable! */
- BPTR pm_Lock; /* Hands off! */
- unsigned char *pm_Name; /* Hands off! */
- unsigned char pm_FileName[108]; /* Hands off! */
- unsigned char pm_Dir[256]; /* Hands off! */
- struct GfxBase *pm_GfxBase; /* At least v33 */
- struct IntuitionBase *pm_IntuitionBase; /* At least v36 */
- struct Library *pm_GadToolsBase; /* At least v36 */
- struct Library *pm_DiskfontBase; /* At least v33 */
- struct Library *pm_AslBase; /* At least v38 */
- struct Library *pm_IconBase; /* At least v33 */
- struct LocaleBase *pm_LocaleBase; /* At least v1 */
- struct Library *pm_WorkbenchBase; /* At least v36 */
- void *VisualInfo; /* Never release it! */
- struct DrawInfo *DrawInfo; /* Never release it! */
- unsigned char *pm_RegionStart;
- unsigned int pm_RegionSize;
- unsigned char *pm_TextStart;
- unsigned char *pm_TextEnd;
- unsigned char *pm_BlockStart;
- unsigned char *pm_BlockEnd;
- struct TextAttr *pm_FontAttr;
- struct TextFont *pm_Font;
- struct Window *pm_EdWindow;
- unsigned int pm_TabWidth; /* In pixels */
- unsigned int pm_TabStops; /* A tap stop occurs every 'n' */
- unsigned int pm_RightMargin;
- unsigned char *pm_CharSpace; /* Pointer to the character-spaces of the used font */
- void (*pm_GetAttr)( struct TagItem *taglist); /* Currently NULL (out of order!) */
- void (*pm_ChangeAttr)( struct TagItem *taglist); /* Currently NULL (out of order!) */
- void (*pm_BlockInput)( void);
- void (*pm_AllowInput)( void);
- void (*pm_Tell)( STRPTR str);
- unsigned int (*pm_CaseTell)( STRPTR str);
- unsigned int (*pm_RequestNumber)( unsigned int initial, STRPTR winname, STRPTR hailtext,\
- STRPTR gadtext, BOOL zero);
- unsigned int (*pm_StrPixelLen)( unsigned char *start, unsigned char *end);
- void (*pm_DumpStrLine)( unsigned char *start, unsigned char *end, struct RastPort *rp,\
- unsigned int x, unsigned int y);
- unsigned int (*pm_WidestStrLen)( unsigned char *text, unsigned char *stop,\
- unsigned int (*inform_code)( unsigned int len, unsigned int line),\
- unsigned int inform);
- void (*pm_DumpStrings)( struct RastPort *rp,\
- unsigned int (*dump_code)( unsigned int len, unsigned int line),\
- unsigned char *text, unsigned char *stop);
- void (*pm_FreeProgressBar)( struct ProgressBar *pb);
- struct ProgressBar *(*pm_CreateProgressBar)( STRPTR wintitle, STRPTR hail, STRPTR stop, STRPTR cont, STRPTR cancel);
- unsigned int (*pm_PullPBarEvent)( struct ProgressBar *pb);
- void (*pm_ChangePBarIndicator)( struct ProgressBar *pb, unsigned int percent, STRPTR hail);
- /* Following does not yet work properly - so don't use! */
- void (*pm_TogglePBarGad)( struct ProgressBar *pb);
- };
-
-
- /* ----------------------------------------------------------------------------------------------- */
-
- struct PseudoMsg *PsMsg; /* Message got from BareED */
-
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
- struct LocaleBase *LocaleBase;
- struct Library *GadToolsBase;
-
- struct Catalog *Cat;
-
- union PrinterIO
- {
- struct IOStdReq IoStd;
- struct IODRPReq IoDpRP;
- struct IOPrtCmdReq IoPrtCom;
- };
-
- struct MsgPort *PrinterPort;
- union PrinterIO *PIO;
- struct PrinterData *PD;
- struct PrinterExtendedData *PED;
-
- struct ProgressBar *PB; /* Will be created */
-
- struct RastPort *FakeRP;
- struct BitMap *FakeBM;
- struct ColorMap *CM;
-
- /* Since "printer device" destroys them, I have to remember them! */
- unsigned int DestHDots, DestVDots, ModeID;
- unsigned int VDotsPage, VDotsLine, HDotsLine, Lines;
-
- /* Want to show user how much alredy worked out... */
- unsigned int Lines2Dump; /* Amount total lines in printout */
-
- #define TEXTBUFFERSIZE 256 /* Storage size (buffer) for strings */
- STRPTR TextBuffer;
-
- BOOL Continue = TRUE; /* While Continue is TRUE we continue - when FALSE, we quit */
-
- BOOL IoStarted = FALSE; /* When the IO is in progress, it will be TRUE */
-
- /* Offset on paper and keep track of actual line dumped */
- unsigned CurrYdot, CurrLine;
-
-
- /* Possible printer.device and I/O errors */
- STRPTR ErrorText[] =
- {
- "\000\x0A No error",
- "\000\x0B Printing-progress aborted",
- "\000\x0C Not a graphic printer",
- "\000\x0D HAM image cannot be converted", /* Cannot occur */
- "\000\x0E Too large region to dump",
- "\000\x0F Out of supported dimension", /* Cannot occur */
- "\000\x10 Not enough memory",
- "\000\x11 Not enough memory for print-buffer",
- "\000\x12 IO: Open device failed",
- "\000\x13 IO: Printing-progress aborted",
- "\000\x14 IO: Unsupported command",
- "\000\x15 IO: Command length did not match"
- };
-
- /* ---------------------------------------------------------------------
- I don't want to waste memory so I use an own made SPrintf() function
- which is much shorter (it doesn't support floats and word descriptions)
- than the original!
- */
-
- #if defined(__MAXON__)
- void ASM funny_code( REG(a3, char *buf), REG(d0, char c))
- {
- *buf++ = c; // move.b d0,(a3)+
- } // rts
- #else
- unsigned short funny_code[] =
- {
- 0x16c0,
- 0x4e75
- };
- #endif
-
- #define FUNC (void (*)()) &funny_code /* Code should use: lea funny_code(An),a2 */
-
- void SPrintf( char *buf, char *descr, ...)
- {
- char *args;
-
- (char *) args = (char *) &descr; /* Address format string on stack */
- args += 4; /* Address 1st additional argument */
- RawDoFmt( descr, args, FUNC, buf);
- }
-
- /* -----------------------
- Multilingual stuff...
-
- NOTE: I prepared the strings so that they contain a leading word, which is set up as follow:
- 1st byte (an octal number)
- 2nd byte (an octal or hexadecimal number)
- 3rd byte - dummy (space character)
- 4th byte - string start
- The first two bytes (= one word) will be converted by GStr() to a longword - used as index
- in the catalogue.
- */
-
- void OpenTheCatalog()
- {
- Cat = (struct Catalog *) OpenCatalogA( 0, "dac_dump.catalog", 0);
- }
-
- void CloseTheCatalog()
- {
- if (Cat)
- CloseCatalog( Cat);
- }
-
- char * GStr( char *str)
- {
- ULONG no;
- char *rstr;
-
- no = 0;
- no = ( (UBYTE) str[0] << 8) + (UBYTE) str[1]; /* Convert the two leading bytes of string into longword */
- rstr = &str[3]; /* String's start */
-
- if (Cat)
- rstr = (char *) GetCatalogStr( Cat, no, rstr); /* Get string or the default... */
-
- return rstr;
- }
-
-
- /* ---------------------------------
- CallBack Hook for WidestStrLen()
-
- No need here to save / load base register! - already done!
-
- Inform user if a line exeeds the computed limit. Routine
- called from the inside of WidestStrLen() !
- */
-
- unsigned int InformCode( unsigned int len, unsigned int line)
- {
- unsigned int limit;
-
- limit = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
-
- SPrintf( TextBuffer, GStr( "\001\001 Line %ld exceeds with %ld pixels limit of %ld pixels!\n\n"\
- "Continue anyhow?"), line, len, limit);
- Continue = PsMsg->pm_CaseTell( TextBuffer);
-
- return Continue;
- }
-
-
- /* --------------------------------
- CallBack Hook for DumpStrings()
-
- No need here to save / load base register! - already done!
-
- This routine is called from DumpStrings() - when DumpStrings()
- has laid out a new line - thus we can here dump the Raster Port
- contents to the printer. Meanwhile we check for user actions -
- like pause, continue or abandon the printout.
- */
-
- unsigned int DumpCode( unsigned int len, unsigned int line)
- {
- BOOL cont = TRUE;
- unsigned int signal, sigPrt, sigWd, id, spec, flag, percent, permil, loop;
- int i;
-
- /* Check if the dump will need a new page */
- if ( VDotsPage < CurrYdot + VDotsLine) /* Fits this line onto paper? */
- {
- /* Remember both - to set them later on! */
- spec = PIO->IoDpRP.io_Special;
- flag = PIO->IoDpRP.io_Flags;
-
- PIO->IoStd.io_Flags = IOF_QUICK; /* Need no reply from "printer.device" */
- PIO->IoStd.io_Command = CMD_WRITE;
- PIO->IoStd.io_Length = 1;
- PIO->IoStd.io_Data = "\014"; /* Eject page (12 = FormFeed) */
-
- if (IoStarted)
- WaitIO( (struct IORequest *) PIO); /* Wait until line has been dumped */
- IoStarted = FALSE;
- if ( DoIO( (struct IORequest *) PIO))
- cont = PsMsg->pm_CaseTell( GStr( "\000\x16 Error occurred while ejecting the page!\n\n"\
- "Continue anyway?") );
- IoStarted = cont;
- /* Re-do for graphic dump */
- PIO->IoDpRP.io_Command = PRD_DUMPRPORT;
- PIO->IoDpRP.io_Flags = flag;
- PIO->IoDpRP.io_RastPort = FakeRP;
- PIO->IoDpRP.io_ColorMap = CM;
- PIO->IoDpRP.io_Modes = ModeID;
- PIO->IoDpRP.io_SrcX = 0;
- PIO->IoDpRP.io_SrcY = 0;
- PIO->IoDpRP.io_SrcWidth = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
- PIO->IoDpRP.io_SrcHeight = PsMsg->pm_Font->tf_YSize + 1;
- PIO->IoDpRP.io_Special = spec;
- PIO->IoDpRP.io_DestCols = DestHDots;
- PIO->IoDpRP.io_DestRows = DestVDots;
-
- CurrYdot = 0; /* Set to top of page */
- }
-
- if (cont == TRUE)
- {
- /* Send to printer... */
- if (IoStarted)
- WaitIO( (struct IORequest *) PIO); /* Wait for last action to be completed */
- SendIO( (struct IORequest *) PIO); /* Attempt to dump Raster Port */
- IoStarted = TRUE;
- CurrYdot += VDotsLine; /* Next offset (plus full line) */
- CurrLine ++; /* One more line dumped */
-
- /* In case the progress-bar is accessible... */
- if (PB)
- {
- percent = CurrLine * 100 / Lines2Dump; /* How much in percent already worked out? */
- permil = CurrLine * 1000 / Lines2Dump;
- permil = permil - (percent * 10);
- SPrintf( TextBuffer, GStr( "\000\x46 Printout completed to %ld.%ld %%"), percent, permil);
- PsMsg->pm_ChangePBarIndicator( PB, percent, TextBuffer);
- }
-
- /* The following construct emulates the WaitIO() function but gives us
- also the chance to set and wait for other, non "printer device" related
- things, here break signal (CTRL-C) and progress-bar message
- */
- sigPrt = 1 << PrinterPort->mp_SigBit; /* Signal-bitmask of printer */
- if (PB)
- sigWd = 1 << PB->pb_Window->UserPort->mp_SigBit; /* and ditto for progress-bar */
- else
- sigWd = 0;
- signal = Wait( SIGBREAKF_CTRL_C | sigPrt | sigWd ); /* Cheap sleep! */
-
-
- /* Break signal from the outside (system monitor) ? */
- if ( (signal & SIGBREAKF_CTRL_C) )
- {
- AbortIO( (struct IORequest *) PIO);
- if (IoStarted)
- WaitIO( (struct IORequest *) PIO); /* Convention */
- PsMsg->pm_Tell( GStr ("\000\x17 Printing abandoned by user!") );
- cont = FALSE;
- }
-
-
- /* Message from "printer device" ? */
- if (cont == TRUE)
- {
- if ( (signal & sigPrt) )
- while ( GetMsg( PrinterPort)); /* Remove only the message */
-
- /* Check for error */
- if (PIO->IoDpRP.io_Error)
- {
- i = PIO->IoDpRP.io_Error;
- if (i < 0) /* IO error ? */
- i = i * -1 + 7; /* Map to offset in table */
- SPrintf( TextBuffer, GStr( "\000\x18 Error: %s"), GStr( ErrorText[i]) );
- PsMsg->pm_Tell( TextBuffer);
- cont = FALSE;
- }
- }
-
-
- /* Progress-bar message? */
- if (cont == TRUE)
- {
- if ( (signal & sigWd) )
- {
- id = PsMsg->pm_PullPBarEvent( PB); /* Get id of gadget clicked */
-
- /* Pause? */
- if (id == 2)
- {
- spec = PIO->IoDpRP.io_Special; /* Remember current state */
- flag = PIO->IoDpRP.io_Flags;
-
- WaitIO( (struct IORequest *) PIO); /* Wait for dump in progress to be completed */
- PIO->IoStd.io_Flags = IOF_QUICK; /* Need no reply */
- PIO->IoStd.io_Command = CMD_STOP; /* Stop dump (already completed but necessary) */
- DoIO( (struct IORequest *) PIO); /* Do it now! */
- IoStarted = FALSE;
-
- loop = TRUE;
- while (loop)
- {
- signal = Wait( SIGBREAKF_CTRL_C | sigPrt | sigWd);
-
- /* A break signal from the outside? */
- if (signal & SIGBREAKF_CTRL_C)
- {
- AbortIO( (struct IORequest *) PIO);
- if (IoStarted)
- WaitIO( (struct IORequest *) PIO); /* Convention */
- PsMsg->pm_Tell( GStr ("\000\x17 Printing abandoned by user!") );
- cont = FALSE;
- loop = FALSE;
- }
-
-
- if (cont && loop)
- {
- /* Message from device? - can only be "stopped"! */
- if ( (signal & sigPrt) )
- while ( GetMsg( PrinterPort)); /* Remove only the message */
-
- /* Check for error */
- if (PIO->IoDpRP.io_Error)
- {
- i = PIO->IoDpRP.io_Error;
- if (i < 0) /* IO error ? */
- i = i * -1 + 7; /* Map to offset in table */
- SPrintf( TextBuffer, GStr( "\000\x18 Error: %s"), GStr( ErrorText[i]) );
- PsMsg->pm_Tell( TextBuffer);
- cont = FALSE;
- loop = FALSE;
- }
- }
-
-
- /* Message from progress-bar? - note: we're paused! */
- if ( loop && (signal & sigWd) )
- {
- id = PsMsg->pm_PullPBarEvent( PB); /* Get id of gadget clicked */
-
- if (id == 2) /* awake? */
- {
- PIO->IoStd.io_Flags = IOF_QUICK;
- PIO->IoStd.io_Command = CMD_START; /* Continue dump (i.e. tell device we're */
- DoIO( (struct IORequest *) PIO); /* going to re-use it) */
-
- /* Re-do for graphic dump */
- PIO->IoDpRP.io_Command = PRD_DUMPRPORT;
- PIO->IoDpRP.io_Flags = flag;
- PIO->IoDpRP.io_RastPort = FakeRP;
- PIO->IoDpRP.io_ColorMap = CM;
- PIO->IoDpRP.io_Modes = ModeID;
- PIO->IoDpRP.io_SrcX = 0;
- PIO->IoDpRP.io_SrcY = 0;
- PIO->IoDpRP.io_SrcWidth = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
- PIO->IoDpRP.io_SrcHeight = PsMsg->pm_Font->tf_YSize + 1;
- PIO->IoDpRP.io_Special = spec;
- PIO->IoDpRP.io_DestCols = DestHDots;
- PIO->IoDpRP.io_DestRows = DestVDots;
- loop = FALSE;
- }
- else
- {
- if (id == 1) /* Shame on user, firstly paused now abandoned... */
- {
-
- PIO->IoStd.io_Flags = IOF_QUICK;
- PIO->IoStd.io_Command = CMD_FLUSH; /* Abort halted IO-requests */
- DoIO( (struct IORequest *) PIO);
- if (IoStarted)
- WaitIO( (struct IORequest *) PIO);
- PsMsg->pm_Tell( GStr ("\000\x17 Printing abandoned by user!") );
- cont = FALSE;
- loop = FALSE;
- }
- }
- }
- }
- }
- else
- {
- /* User said stop and quit? */
- if (id == 1)
- {
- AbortIO( (struct IORequest *) PIO);
- if (IoStarted)
- WaitIO( (struct IORequest *) PIO);
- PsMsg->pm_Tell( GStr ("\000\x17 Printing abandoned by user!") );
- cont = FALSE;
- }
- }
- }
- } /* End progress-bar message */
-
-
- /* Firstly, clear the complete bit-plane(s) */
- SetDrMd( FakeRP, JAM2); /* We want to overwrite */
- SetAPen( FakeRP, 0); /* Background pen */
- RectFill( FakeRP, 0, 0, FakeBM->BytesPerRow * 8 - 1, FakeBM->Rows - 1);
-
- /* Set render pen - to make the characters visible */
- SetAPen( FakeRP, 1); /* Foreground pen */
- }
-
- return cont;
- }
-
- /* ----------------------------------------------------
- Try to dump the specified characters to the printer
-
- Called with the widest string length in pixels.
-
- NOTE:
- The 'FakeBM->Depth' must have already been set to the required depth -
- in this example it was set to one (monochrome).
- */
-
- void DoTheDump( unsigned int mustHave)
- {
- unsigned int i, a, r, p;
- unsigned char *curr, *end;
-
- a = mustHave / PsMsg->pm_CharSpace[ (UBYTE) ' '];
-
- if (PsMsg->pm_RightMargin < a)
- i = PsMsg->pm_CaseTell( GStr( "\001\002 Sure to continue with printout\n"\
- "although not all characters fit onto concerned page?\n"\
- "(Some beyond right margin - non-printable!)\n\n"\
- "Continue?") );
- if (i)
- {
- /* Compute size in bytes for bit-plane allocation */
- i = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32]; /* Size in pixels */
- i = (i + 15) & -16; /* 16-bit boundary */
- i /= 8; /* ...in bytes */
- FakeBM->BytesPerRow = i; /* Amount of rows */
-
- FakeBM->Rows = PsMsg->pm_Font->tf_YSize + 1;
-
- if (GfxBase->LibNode.lib_Version <= 38 \
- || (GetBitMapAttr( PsMsg->pm_EdWindow->WScreen->RastPort.BitMap, BMA_FLAGS) & BMF_STANDARD))
- {
- /* Standard (PLANAR) display - so the bitplanes must reside in CHIP-RAM -
- for the rendering functions
- */
- FakeBM->Planes[0] = (PLANEPTR) AllocMem( FakeBM->BytesPerRow * FakeBM->Rows * FakeBM->Depth, \
- MEMF_CLEAR|MEMF_CHIP);
- }
- else
- {
- /* There is a non-standard Bitmap - so I guess rendering to FAST-RAM will work! */
- FakeBM->Planes[0] = (PLANEPTR) AllocMem( FakeBM->BytesPerRow * FakeBM->Rows * FakeBM->Depth, MEMF_CLEAR);
- }
-
- /* Bitplane(s) allocated? */
- if ( FakeBM->Planes[0])
- {
- /* If the Bitmap has got more than 1 Bitplane the construct below will
- compute the other Bitplane addresses and stores them into the Bitmap
- */
- a = (unsigned int) FakeBM->Planes[0]; /* Address allocated memory, bitplane[0] already set! */
- for (i = 1; i < FakeBM->Depth; i++) /* Do it for the others (?) */
- {
- a += FakeBM->BytesPerRow * FakeBM->Rows; /* Plus size of one, single bitplane */
- FakeBM->Planes[i] = (PLANEPTR) a; /* Store computed address */
- }
-
- /* Figure out if user wishes only to dump the marked area */
- if (PsMsg->pm_BlockStart)
- {
- curr = PsMsg->pm_BlockStart;
- end = PsMsg->pm_BlockEnd;
- }
- else /* No marked area, so take whole archive */
- {
- curr = PsMsg->pm_TextStart;
- end = PsMsg->pm_TextEnd;
- }
-
- /* How many lines are in the archive/text block ? */
- a = 1;
- while (curr < end && *curr != 0)
- if (*curr++ == 10) /* Count linefeeds */
- a++;
- Lines2Dump = a; /* Remember for later */
-
- /* How many lines can be displayed per printer page? */
- i = PD->pd_Preferences.PaperLength; /* Lines per page */
-
- /* How many lines can be displayed per inch */
- if (PD->pd_Preferences.PrintSpacing)
- r = 8;
- else
- r = 6;
-
- /* How many dots can be printed out to one page in vertical direction? */
- i = i * PED->ped_YDotsInch / r; /* e.g. 66 lines * 180 dpi / 6 lines per page */
-
- /* How many pages required to print out those lines? */
- p = a * PIO->IoDpRP.io_DestRows / i;
- if (!p)
- p = 1; /* At least one page! */
-
- /* Check if there is a rest of lines that need an extra page,
- e.g. 60 lines per page , 153 lines to print but only 2 pages computed!
- */
- if (a > p * i / PIO->IoDpRP.io_DestRows)
- p ++;
-
- /* Give the user the chance to abort printing... */
- SPrintf( TextBuffer, GStr( "\001\003 Sure to print?\n\nPrintout would require %ld pages!"), p);
- p = PsMsg->pm_CaseTell( TextBuffer);
- if (p)
- {
- /*
- 'i' contains vertical dots per page, e.g. 1920,
- 'a' contains amount lines to print
- 'PIO->IoDpRP.io_DestCols' contains horizontal dots for a single line to print
- 'PIO->IoDpRP.io_DestRows' contains vertical dots for a single line to print
- */
- VDotsPage = i;
- VDotsLine = PIO->IoDpRP.io_DestRows;
- HDotsLine = PIO->IoDpRP.io_DestCols;
- Lines = a;
- CurrYdot = 0; /* Imagine we're at the top of a page */
- CurrLine = 0; /* No lines printed (yet) */
-
- CM = GetColorMap( 2); /* Monochrome - only two colours */
- if (CM)
- {
- SetRGB4CM( CM, 0, 0xF, 0xF, 0xF); /* Background = white */
- SetRGB4CM( CM, 1, 0x0, 0x0, 0x0); /* Foreground = black */
-
- /* Establish this colour-map for dump */
- PIO->IoDpRP.io_ColorMap = CM;
-
- /* We really want to print! */
- PIO->IoDpRP.io_Special &= ~SPECIAL_NOPRINT;
-
- SetDrMd( FakeRP, JAM2); /* We want to overwrite */
- SetAPen( FakeRP, 1); /* Foreground pen */
- SetBPen( FakeRP, 0); /* Background pen */
-
- PB = PsMsg->pm_CreateProgressBar( GStr( "\002\001 DAC Dumper"), \
- GStr( "\000\x42 Printout completed to 0.0"), \
- GStr( "\000\x43 Pause/Continue"), GStr( "\000\x44 Continue"), \
- GStr( "\000\x45 Abandon") );
-
- /* Continue even the progress-bar has not been attached to Dump */
- if (PsMsg->pm_BlockStart)
- PsMsg->pm_DumpStrings( FakeRP, &DumpCode, PsMsg->pm_BlockStart, PsMsg->pm_BlockEnd);
- else
- PsMsg->pm_DumpStrings( FakeRP, &DumpCode, PsMsg->pm_TextStart, PsMsg->pm_TextEnd);
-
- if (PB)
- PsMsg->pm_FreeProgressBar( PB);
-
- /* REMOVED - since it should be clear...
- PsMsg->pm_Tell( GStr( "\002\004 Print-job done.") ); */
-
- FreeColorMap( CM);
- }
- else
- PsMsg->pm_Tell( GStr( "\000\x19 Cannot create unicoloured colour-map!") );
- }
- FreeMem( FakeBM->Planes[0], FakeBM->BytesPerRow * FakeBM->Rows * FakeBM->Depth);
- }
- else
- PsMsg->pm_Tell( GStr( "\000\x1A Unable to get RAM for printout!") );
- }
- else
- PsMsg->pm_Tell( GStr( "\000\x1B Print-job aborted...") );
-
- }
-
-
- /* ###############################################################
- Here we go...
- */
-
- int main( int argc, char **argv)
- {
- struct ViewPort *vp;
- int a, i, p, l;
-
- /* Discover if we have been launched by Workbench */
- if ( !WBenchMsg)
- return 0;
-
- /* Either from Workbench or BareED */
- if ( strcmp( WBenchMsg->sm_Message.mn_Node.ln_Name, "BAREED") != NULL)
- return 0;
-
- /* Was BareED, so convert pointer to the message */
- PsMsg = (struct PseudoMsg *) WBenchMsg;
-
- GfxBase = PsMsg->pm_GfxBase;
- IntuitionBase = (struct IntuitionBase *) PsMsg->pm_IntuitionBase;
- LocaleBase = PsMsg->pm_LocaleBase;
- GadToolsBase = PsMsg->pm_GadToolsBase;
-
- OpenTheCatalog();
-
- TextBuffer = (STRPTR) AllocMem( TEXTBUFFERSIZE, MEMF_CLEAR);
- FakeRP = (struct RastPort *) AllocMem( sizeof( struct RastPort), MEMF_CLEAR);
- FakeBM = (struct BitMap *) AllocMem( sizeof( struct BitMap), MEMF_CLEAR);
-
- if (TextBuffer && FakeRP && FakeBM)
- {
- /* Create non-public message port */
- if ( (PrinterPort = CreateMsgPort()) )
- {
- /* Allocate PrinterIO - for easier access as union */
- if ( (PIO = (union PrinterIO *) CreateExtIO( PrinterPort, sizeof( union PrinterIO))) )
- {
- /* Open the printer.device */
- if ( !(OpenDevice( "printer.device", 0, (struct IORequest *) PIO, 0)) )
- {
- PD = (struct PrinterData *) PIO->IoDpRP.io_Device;
- PED = (struct PrinterExtendedData *) &PD->pd_SegmentData->ps_PED;
-
- vp = &(PsMsg->pm_EdWindow->WScreen->ViewPort);
-
- /* Get the mode-id to compute correct aspect ratio */
- if ( (ModeID = GetVPModeID( vp)) != INVALID_ID)
- {
- /* Create a faked Raster Port so that a BAD DIMENSION error is nearly impossible!
- To do this:
- Tell the "printer.device" that the faked Bitmap is in horizontal direction
- ten times larger than screen's! Could also be done with a fixed-width size,
- e. g. 16000.
- Since no rendering is performed, we can play with empty bitplanes!
- */
-
- /* Duplicate Raster Port - a bad hack? */
- CopyMem( PsMsg->pm_EdWindow->RPort, FakeRP, sizeof( struct RastPort));
- FakeRP->Layer = 0;
- FakeRP->BitMap = FakeBM;
- FakeBM->BytesPerRow = PsMsg->pm_EdWindow->WScreen->Width * 10 / 8;
- FakeBM->Rows = PsMsg->pm_EdWindow->WScreen->Height;
- FakeBM->Depth = 1;
-
- /* Fill in parts of the IODRPRequest - used to compute correct aspect ratio */
- PIO->IoDpRP.io_Command = PRD_DUMPRPORT;
- PIO->IoDpRP.io_RastPort = FakeRP;
- PIO->IoDpRP.io_ColorMap = vp->ColorMap;
- PIO->IoDpRP.io_Modes = ModeID;
- PIO->IoDpRP.io_SrcX = 0;
- PIO->IoDpRP.io_SrcY = 0;
-
- /* We need a valid right margin to compute and lay out strings! */
- while (PsMsg->pm_RightMargin == NULL)
- PsMsg->pm_RightMargin = PsMsg->pm_RequestNumber( 0, GStr( "\002\001 DAC Dumper"),\
- GStr( "\002\002 Enter right margin!"),\
- GStr( "\002\003 Okay"), 0);
-
- /* How long is a line in pixels? */
- PIO->IoDpRP.io_SrcWidth = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
-
- /* How high is the font (plus one because BareED reserves between each text line a row! */
- PIO->IoDpRP.io_SrcHeight = PsMsg->pm_Font->tf_YSize + 1;
-
- /* We don't want to print, but we want to know the correct dimension */
- PIO->IoDpRP.io_Special = SPECIAL_ASPECT|SPECIAL_NOFORMFEED|SPECIAL_TRUSTME|SPECIAL_NOPRINT;
-
- /* Initialise with zero so "printer device" calculates dump dimension! */
- PIO->IoDpRP.io_DestCols = 0;
- PIO->IoDpRP.io_DestRows = 0;
-
- /* Ask for dimension */
- DoIO( (struct IORequest *) PIO);
-
- if (PIO->IoDpRP.io_Error == 0)
- {
- DestHDots = p = PIO->IoDpRP.io_DestCols; /* Dots in horizontal direction
- (to fit line fulfilled onto paper) */
- DestVDots = l = PIO->IoDpRP.io_DestRows; /* Dots in vertical direction (height of
- one single line!) */
- }
- else
- {
- a = PIO->IoDpRP.io_Error;
- if (a < 0)
- a = a * -1 + 7;
-
- SPrintf( TextBuffer, GStr( "\000\x18 Error: %s"), GStr( ErrorText[a]));
- PsMsg->pm_Tell( TextBuffer);
- }
-
- /* Do not continue upon error */
- if ( !PIO->IoDpRP.io_Error)
- {
- /* How wide is a string basing on RightMargin (in pixels -
- as limit for WidestStrLen()) ?
- */
- a = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
-
- /* Get the height of the font and care about the row that BareED reserves
- between each text line
- */
- i = PsMsg->pm_Font->tf_YSize + 1;
-
- SPrintf( TextBuffer, GStr( "\000\x40 Dimension when using a right margin of %ld" \
- " characters:\n\nline length = %4ld pixles = X-dots = %4ld\n" \
- "line height = %4ld pixels = Y-dots = %4ld"), \
- PsMsg->pm_RightMargin, a, p, i, l);
- PsMsg->pm_Tell( TextBuffer);
-
- /* Invoke function WidestStrLen() with a set CallBack-Hook */
- if (PsMsg->pm_BlockStart)
- p = PsMsg->pm_WidestStrLen( PsMsg->pm_BlockStart, PsMsg->pm_BlockEnd,\
- &InformCode, a);
- else
- p = PsMsg->pm_WidestStrLen( PsMsg->pm_TextStart, PsMsg->pm_TextEnd,\
- &InformCode, a);
-
- /* Did the user abandoned computing? */
- if (Continue)
- {
- /* No... */
- l = p / PsMsg->pm_CharSpace[ (UBYTE) 32];
- if ( l * PsMsg->pm_CharSpace[ (UBYTE) 32] < p) /* Correct number of chars! */
- l ++;
-
- SPrintf( TextBuffer, GStr( "\000\x41 Widest line: %ld pixels or %ld characters!"), p, l);
- PsMsg->pm_Tell( TextBuffer);
-
-
- /* Now, compute X-offset for printout. Take "Printer-Prefs" left margin - not
- "PrinterGfx-Prefs" settings!
- */
- i = PD->pd_Preferences.PrintXOffset; /* Remember to restore later */
-
- l = PD->pd_Preferences.PrintSpacing >> 10; /* Get used printer's font */
- if (l == 0)
- l = 10; /* Pica 10 cpi */
- if (l == 1)
- l = 12; /* Elite 12 cpi */
- if (l == 2)
- l = 17; /* Fine 15/17 cpi */
-
- /* E. g.: 30 (left margin) * 10 / 10 (Pica = 10 cpi) = 30(/10ths inch) */
- PD->pd_Preferences.PrintXOffset = PD->pd_Preferences.PrintLeftMargin * 10 / l;
-
- /* Print out graphic */
- DoTheDump( p);
-
- PD->pd_Preferences.PrintXOffset = i;
- }
- }
- }
- else
- PsMsg->pm_Tell( GStr( "\000\x1C Invalid screen-mode-ID") );
-
- CloseDevice( (struct IORequest *) PIO);
- }
- else
- PsMsg->pm_Tell( GStr( "\000\x1D Cannot open the \"printer device\"") );
-
- DeleteExtIO( (struct IORequest *) PIO);
-
- }
- else
- PsMsg->pm_Tell( GStr( "\000\x1E Cannot create required I/O-request") );
-
- DeleteMsgPort( PrinterPort);
-
- }
- else
- PsMsg->pm_Tell( GStr( "\000\x1F Cannot create a message port") );
-
- }
-
- if (FakeBM)
- FreeMem( FakeBM, sizeof( struct BitMap));
- if (FakeRP)
- FreeMem( FakeRP, sizeof( struct RastPort));
- if (TextBuffer)
- FreeMem( TextBuffer, TEXTBUFFERSIZE);
-
- CloseTheCatalog();
-
- return 0;
- }
-
- /*
- This is the end of DAC-Dump - if you can do better than me - feel free to modify.
- */