跳轉到內容

Aros/開發者/文件/裝置/印表機

來自華夏公益教科書
Aros 華夏公益教科書的導航欄
Aros 使用者
Aros 使用者文件
Aros 使用者常見問題解答
Aros 使用者應用程式
Aros 使用者 DOS Shell
Aros/使用者/AmigaLegacy
Aros 開發文件
Aros 開發者文件
從 AmigaOS/SDL 移植軟體
針對 Zune 初學者
Zune .MUI 類
針對 SDL 初學者
Aros 開發者構建系統
特定平臺
Aros x86 完整系統 HCL
Aros x86 音訊/影片支援
Aros x86 網路支援
Aros 英特爾 AMD x86 安裝
Aros 儲存支援 IDE SATA 等
Aros Poseidon USB 支援
x86-64 支援
摩托羅拉 68k Amiga 支援
Linux 和 FreeBSD 支援
Windows Mingw 和 MacOSX 支援
Android 支援
Arm 覆盆子派支援
PPC Power 架構
雜項
Aros 公共許可證

AmigaDOS 3.1(AROS 模仿的物件)沒有像您在其他作業系統中看到的那樣的標準列印對話方塊,用於選擇要列印的文件頁數、選擇橫向模式與縱向模式、紙張尺寸、紙張型別、雙面模式、列印預覽等。每個程式都必須自行滾動以與印表機首選項介面以進行這些操作。

在 AmigaDOS 1.x-3.1 中,每個應用程式程式都必須對高解析度、高質量列印進行自己的支援,因為圖形顯示和列印 API 沒有任何解析度獨立性內建在建立和顯示繪圖命令列表中,然後將該列表轉換為結構化的繪圖格式或語言輸出,包括徽標或字型等。(與 MacOS 或 Windows 不同)。

在 AmigaDOS 1.x-3.1 中,列印由一個原始的 printer.device 組成,它只理解 ANSI 格式的文字和幾種型別的圖形 rastport 二進位制資料,並查詢 printer、printergfx 和 printerps 首選項以決定如何處理列印到點陣圖方向印表機、ANSI 序列文字印表機或透過饋送原始資料(由希望列印原始資料的每個單獨程式獨立生成)。每臺印表機都會有一個為其定製的裝置檔案,用於在文字和圖形之間切換模式(從內部 Amiga 圖形或文字格式轉換為印表機喜歡的格式),並執行諸如走紙、設定邊距等操作,printer.device 將(透過印表機首選項)決定將該資料傳送到哪個埠,檢查列印時的錯誤等。

目前,AROS 支援將任何文字和圖片轉換為 Postscript (.ps) 檔案,然後可以將這些檔案儲存為檔案或列印到有限範圍的印表機。

使用現有的 printer.device API
  • PRD_RAWWRITE 將未處理的資料傳送到印表機
  • PRD_DUMPRPORT (IODRPReq->ioCommand) 將 rastport 傳送到印表機
  • PRD_QUERY (IOStdReq->io_Command) 印表機埠處於什麼狀態
  • PRD_PRTCOMMAND (IOPrtCmdReq->ioCommand) 透過 CMD_WRITE 將 ANSI 轉義序列傳送到印表機(不支援)
將輸出寫入
  • 使用者指定的(透過首選項或彈出視窗)檔名
  • 到另一個程式的管道(透過首選項或彈出請求器)
  • 輸出是 PostScript Level 2(或更低版本)
  • 選擇 A4、Letter 或自定義(以英寸或毫米為單位)的頁面大小

狀態

  • printer.device 的程式碼完成率約為 99%
  • L:port-handler 程式碼已完成
  • C:Print 程式碼已完成(透過 Datatypes 列印)
  • DEVS:Printers/PostScript 的程式碼完成率約為 95%

特點

+ All 10 printer.device units should be available
+ Each unit runs in its own DOS Process
+ Each unit has its own instance of a DEVS:Printer/* driver
+ The instance only exists while the unit is open.
+ Print to file, serial, parallel, or USB (the last 3 are untested)
+ PAR: SER: and PRT: DOS handlers for printing (and general IO) 
  - Of note, see DEVS:DosDrivers/SER0 - it can be adapted for to connect to any streaming device. 
+ Landscape/Portrait works
+ PostScript Level 2, with %%Page: and EPS compatible comments - makes enscript happier 

已知問題

- Only PCC_BGR printers are supported at this time (I'll get CYMK and B&W working in a bit)
- Only (due to licensing [1]) PostScript and Skeleton (demo) printers are available.
- Centering, color inversion, and a number of other minor features are missing or broken.
- No attempt is made to correct the aspect ratio of the printed pictures. 
  • 幾乎所有可以找到的帶有原始碼的印表機驅動程式都在頂部有一個大大的“版權所有 (c) 19xx Amiga”。希望人們可以使用 PostScript 和 Skeleton 驅動程式來編寫具有更好許可證的印表機驅動程式。
/**************************************************************
**** Print.h : procedures for printing                     ****
**** Free software under GNU license, started on 2/2/2012  ****
**** © AROS Team                                           ****
**************************************************************/

#ifndef PRINT_H
#define PRINT_H

#include "Memory.h"

/* Print a file
 */
BYTE print_file(LINE *svg, unsigned char eol);

/* Get/set current printer.device unit
 *   If unit < 0, gets current printer unit
 *   Otherwise, sets unit to the selected unit
 */
BYTE print_unit(BYTE unit);

#endif
/**************************************************************
**** Print.c : procedures for printing                     ****
**** Free software under GNU license, started on 2/2/2012  ****
**** © AROS Team                                           ****
**************************************************************/
#include <intuition/intuition.h>
#include <libraries/asl.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <proto/exec.h>

#include "Gui.h"
#include "Project.h"
#include "Utility.h"
#include "ProtoTypes.h"
#include "Print.h"
#include "DiskIO.h"

#define  CATCOMP_NUMBERS                        /* Error msg use strings id */
#include "strings.h"

static inline BYTE PWrite(struct IORequest *io, CONST_STRPTR buffer, LONG len)
{
    struct IOStdReq *sio = (struct IOStdReq *)io;

    sio->io_Command = CMD_WRITE;
    sio->io_Data = (APTR)buffer;
    sio->io_Length = len;
    return (DoIO(io) == 0 && sio->io_Actual == len) ? 1 : 0;
}

/* Print a file
*/
BYTE print_file(LINE *svg, unsigned char eol)
{
    STRPTR buf;
    LONG   i;
    BYTE   szeol = szEOL[eol];
    LINE *ln;
    BYTE retval = 0;
    struct IORequest *io;
    struct MsgPort *mp;

    if ((mp = CreateMsgPort())) {
        if ((io = CreateIORequest(mp, sizeof(struct IOStdReq)))) {
            if (0 == OpenDevice("printer.device", print_unit(-1), io, 0)) {
                BusyWindow(Wnd);

                for(ln=svg, buf=NULL, i=0; ln; ln=ln->next)
                {
                    if (i == 0)
                        buf = ln->stream;

                    /* An unmodified line (2nd cond. is for deleted lines) */
                    if (ln->max == 0 && ln->stream-buf == i) {
                        i+=ln->size+szeol;
                    } else {
                        /* Flush preceding unmodified buffer */
                        i -= szeol;
                        if( i>=0 && (PWrite(io, buf, i) != 1 ||
                                PWrite(io, &chEOL[eol], szeol) != 1 ) )
                        {
                                retval = 0;
                                break;
                        }

                        /* Writes the modified line */
                        if( PWrite(io, ln->stream, ln->size) != 1 || (ln->next != NULL &&
                            PWrite(io, &chEOL[eol], szeol) != 1 ) ) {
                            retval = 0;
                            break;
                        }
                        i=0;
                    }
                }
                /* Flush buffer */
                if( i>szeol && PWrite(io, buf, i-szeol) !=1 ) {
                    retval = 0;
                }

                WakeUp(Wnd);

                CloseDevice(io);
            }
            DeleteIORequest(io);
        }
        DeleteMsgPort(mp);
    }

    return retval;
}

/* Get/set current printer.device unit
 *   If unit < 0, do not change current unit
 * Return:
 *   printer unit to be used for printing
 *
 */
BYTE print_unit(BYTE unit)
{
    static BYTE current_unit = 0;

    if (unit >= 0)
        current_unit = unit;

    return current_unit;
}

驅動程式

[編輯 | 編輯原始碼]
/*
 * Copyright (C) 2012, The AROS Development Team.  All rights reserved.
 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
 *
 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
 */

#include <aros/debug.h>
#include <aros/printertag.h>

#include <clib/alib_protos.h>
#include <devices/printer.h>
#include <devices/prtgfx.h>
#include <prefs/printergfx.h>
#include <prefs/printertxt.h>
#include <exec/rawfmt.h>

#include <proto/exec.h>
#include <proto/graphics.h>

/* Support binary compatability with AOS */
#ifdef __mc68000
#undef RAWFMTFUNC_STRING
#define RAWFMTFUNC_STRING (VOID (*)())"\x16\xC0\x4E\x75"
#endif

static LONG sk_Init(struct PrinterData *pd);
static VOID sk_Expunge(VOID);
static LONG sk_Open(union printerIO *ior);
static VOID sk_Close(union printerIO *ior);

static LONG sk_Render(SIPTR ct, LONG x, LONG y, LONG status);
static LONG sk_ConvFunc(UBYTE *buf, UBYTE c, LONG crlf_flag);
static LONG sk_DoPreferences(union printerIO *ior, LONG command);
static VOID sk_CallErrHook(union printerIO *ior, struct Hook *hook);
static LONG sk_DoSpecial(UWORD *command, UBYTE output_buffer[],
                         BYTE *current_line_position,
                         BYTE *current_line_spacing,
                         BYTE *crlf_flag, UBYTE params[]);

static CONST_STRPTR PED_Commands[] = {
    "\377",                             /*  0 aRIS   (reset) */
    "\377\377",                         /*  1 aRIN   (initialize) */
    "\377",                             /*  2 aIND   (linefeed) */
    "\377",                             /*  3 aNEL   (CR/LF) */
    "\377",                             /*  4 aRI    (reverse LF) */
    "\377",                             /*  5 aSGR0  (Courier) */
    "\377",                             /*  6 aSGR3  (italics) */
    "\377",                             /*  7 aSGR23 (no italics) */
    "\377",                             /*  8 aSGR4  (underline) */
    "\377",                             /*  9 aSGR24 (no underline) */
    "\377",                             /* 10 aSGR1  (boldface) */
    "\377",                             /* 11 aSGR21 (no boldface) */
    "\377",                             /* 12 aSFC   (set text color) */
    "\377",                             /* 13 aSBC   (set background color) */
    "\377",                             /* 14 aSHORP0 (normal pitch) */
    "\377",                             /* 15 aSHORP2 (elite) */
    "\377",                             /* 16 aSHORP1 (no elite) */
    "\377",                             /* 17 aSHORP4 (condensed) */
    "\377",                             /* 18 aSHORP3 (no condensed) */
    "\377",                             /* 19 aSHORP6 (enlarge) */
    "\377",                             /* 20 aSHORT5 (no enlarge) */
    "\377",                             /* 21 aDEN6   (shadow) */ 
    "\377",                             /* 22 aDEN5   (no shadow) */
    "\377",                             /* 23 aDEN4   (double strike) */
    "\377",                             /* 24 aDEN3   (no double strike) */
    "\377",                             /* 25 aDEN2   (NLQ) */
    "\377",                             /* 26 aDEN1   (no NLQ) */
    "\377",                             /* 27 aSUS2   (superscript) */
    "\377",                             /* 28 aSUS1   (no superscript) */
    "\377",                             /* 29 aSUS4   (subscript) */
    "\377",                             /* 30 aSUS3   (no subscript) */
    "\377",                             /* 31 aSUS0   (normal) */
    "\377",                             /* 32 aPLU    (partial line up) */
    "\377",                             /* 33 aPLD    (partial line down) */
    "\377",                             /* 34 aFNT0   (Courier) */
    "\377",                             /* 35 aFNT1   (Helvetica) */
    "\377",                             /* 36 aFNT2   (Font 2) */
    "\377",                             /* 37 aFNT3   (Font 3) */
    "\377",                             /* 38 aFNT4   (Font 4) */
    "\377",                             /* 39 aFNT5   (Font 5) */
    "\377",                             /* 40 aFNT6   (Font 6) */
    "\377",                             /* 41 aFNT7   (Font 7) */
    "\377",                             /* 42 aFNT8   (Font 8) */
    "\377",                             /* 43 aFNT9   (Font 9) */
    "\377",                             /* 44 aFNT10  (Font 10) */
    "\377",                             /* 45 aPROP2  (proportional) */
    "\377",                             /* 46 aPROP1  (no proportional) */
    "\377",                             /* 47 aPROP0  (default proportion) */
    "\377",                             /* 48 aTSS    (set proportional offset) */
    "\377",                             /* 49 aJFY5   (left justify) */
    "\377",                             /* 50 aJFY7   (right justify) */
    "\377",                             /* 51 aJFY6   (full justify) */
    "\377",                             /* 52 aJFY0   (no justify) */
    "\377",                             /* 53 aJFY3   (letter space) */
    "\377",                             /* 54 aJFY1   (word fill) */
    "\377",                             /* 55 aVERP0  (1/8" line spacing) */
    "\377",                             /* 56 aVERP1  (1/6" line spacing) */
    "\377",                             /* 57 aSLPP   (form length) */
    "\377",                             /* 58 aPERF   (skip n perfs) */
    "\377",                             /* 59 aPERF0  (no skip perfs) */
    "\377",                             /* 60 aLMS    (left margin) */
    "\377",                             /* 61 aRMS    (right margin) */
    "\377",                             /* 62 aTMS    (top margin) */
    "\377",                             /* 63 aBMS    (bot margin) */
    "\377",                             /* 64 aSTBM   (top & bottom margin) */
    "\377",                             /* 65 aSLRM   (left & right margin) */
    "\377",                             /* 66 aCAM    (no margins) */
    "\377",                             /* 67 aHTS    (horizontal tabs) */
    "\377",                             /* 68 aVTS    (vertical tabs) */
    "\377",                             /* 69 aTBC0   (clear horizontal tab) */
    "\377",                             /* 70 aTBC3   (clear all horiz. tabs) */
    "\377",                             /* 71 aTBC1   (clear vertical tab) */
    "\377",                             /* 72 aTBC4   (clear all vertical tabs) */
    "\377",                             /* 73 aTBCALL (clear all tabs) */
    "\377",                             /* 74 aTBSALL (default tabs) */
    "\377",                             /* 75 aEXTEND (extended chars) */
    "\377",                             /* 76 aRAW    (next N chars are literal) */
};

static CONST_STRPTR cmdTable[] = {
    "aRIS",     /* 0 */
    "aRIN",     /* 1 */
    "aIND",     /* 2 */
    "aNEL",     /* 3 */
    "aRI",      /* 4 */
    "aSGR0",    /* 5 */
    "aSGR3",    /* 6 */
    "aSGR23",   /* 7 */
    "aSGR4",    /* 8 */
    "aSGR24",   /* 9 */
    "aSGR1",    /* 10 */
    "aSGR21",   /* 11 */
    "aSFC",     /* 12 */
    "aSBC",     /* 13 */
    "aSHORP0",  /* 14 */
    "aSHORP2",  /* 15 */
    "aSHORP1",  /* 16 */
    "aSHORP4",  /* 17 */
    "aSHORP3",  /* 18 */
    "aSHORP6",  /* 19 */
    "aSHORT5",  /* 20 */
    "aDEN6",    /* 21 */
    "aDEN5",    /* 22 */
    "aDEN4",    /* 23 */
    "aDEN3",    /* 24 */
    "aDEN2",    /* 25 */
    "aDEN1",    /* 26 */
    "aSUS2",    /* 27 */
    "aSUS1",    /* 28 */
    "aSUS4",    /* 29 */
    "aSUS3",    /* 30 */
    "aSUS0",    /* 31 */
    "aPLU",     /* 32 */
    "aPLD",     /* 33 */
    "aFNT0",    /* 34 */
    "aFNT1",    /* 35 */
    "aFNT2",    /* 36 */
    "aFNT3",    /* 37 */
    "aFNT4",    /* 38 */
    "aFNT5",    /* 39 */
    "aFNT6",    /* 40 */
    "aFNT7",    /* 41 */
    "aFNT8",    /* 42 */
    "aFNT9",    /* 43 */
    "aFNT10",   /* 44 */
    "aPROP2",   /* 45 */
    "aPROP1",   /* 46 */
    "aPROP0",   /* 47 */
    "aTSS",     /* 48 */
    "aJFY5",    /* 49 */
    "aJFY7",    /* 50 */
    "aJFY6",    /* 51 */
    "aJFY0",    /* 52 */
    "aJFY3",    /* 53 */
    "aJFY1",    /* 54 */
    "aVERP0",   /* 55 */
    "aVERP1",   /* 56 */
    "aSLPP",    /* 57 */
    "aPERF",    /* 58 */
    "aPERF0",   /* 59 */
    "aLMS",     /* 60 */
    "aRMS",     /* 61 */
    "aTMS",     /* 62 */
    "aBMS",     /* 63 */
    "aSTBM",    /* 64 */
    "aSLRM",    /* 65 */
    "aCAM",     /* 66 */
    "aHTS",     /* 67 */
    "aVTS",     /* 68 */
    "aTBC0",    /* 69 */
    "aTBC3",    /* 70 */
    "aTBC1",    /* 71 */
    "aTBC4",    /* 72 */
    "aTBCALL",  /* 73 */
    "aTBSALL",  /* 74 */
    "aEXTEND",  /* 75 */
    "aRAW",     /* 76 */
};

static CONST_STRPTR PED_8BitChars[] = {

          " ", /* SPC (160) */
          "?", /* ! */ 
          "?", /* c */ 
          "?", /* £ */
          "?", /* o */
          "?", /* Y */
          "|", 
          "?", /* S */
          "?", 
          "?", /* Copyright */ 
          "?", /* a */
          "?", /* < */ 
          "?", /* - */
          "?", /* SHY */
          "?", /* R */ 
          "?", /* - */
          "?", /* o (176) */
          "?", /* +- */ 
          "?", /* 2 */
          "?", /* 3 */
          "?", 
          "?", /* u */ 
          "?", /* P */ 
          "?", /* . */
          "?", /* , */ 
          "?", /* 1 */
          "?", /* o */
          "?", /* > */
          "?", /* 1/4 */
          "?", /* 1/2 */
          "?", /* 3/4 */ 
          "?", /* ? */
          "?", /* A' (192) */
          "?", /* A' */ 
          "?", /* A^ */ 
          "?", /* A~ */ 
          "?", /* A: */ 
          "?", /* Ao */ 
          "?", /* AE */ 
          "?", /* C */
          "?", /* E' */ 
          "?", /* E' */ 
          "?", /* E^ */ 
          "?", /* E: */ 
          "?", /* I' */ 
          "?", /* I' */ 
          "?", /* I^ */ 
          "?", /* I: */
          "?", /* D- (208) */ 
          "?", /* N~ */ 
          "?", /* O' */ 
          "?", /* O' */ 
          "?", /* O^ */ 
          "?", /* O~ */ 
          "?", /* O: */ 
          "?", /* x  */
          "?", /* 0  */ 
          "?", /* U' */
          "?", /* U' */
          "?", /* U^ */ 
          "?", /* U: */ 
          "?", /* Y' */ 
          "?", /* p  */ 
          "?", /* B  */
          "?", /* a' (224) */
          "?", /* a' */ 
          "?", /* a^ */ 
          "?", /* a~ */ 
          "?", /* a: */ 
          "?", /* ao */ 
          "?", /* ae */ 
          "?", /* c */
          "?", /* e' */ 
          "?", /* e' */ 
          "?", /* e^ */ 
          "?", /* e: */ 
          "?", /* i' */ 
          "?", /* i' */ 
          "?", /* i^ */ 
          "?", /* i: */
          "?", /* o (240) */ 
          "?", /* n~ */ 
          "?", /* o' */ 
          "?", /* o' */ 
          "?", /* o^ */ 
          "?", /* o~ */ 
          "?", /* o: */ 
          "?", /* /  */
          "?", /* 0  */ 
          "?", /* u' */
          "?", /* u' */
          "?", /* u^ */ 
          "?", /* u: */ 
          "?", /* y' */ 
          "?", /* p  */ 
          "?", /* y: */
};

static struct TagItem PED_TagList[] = {
    { PRTA_8BitGuns, TRUE },            /* 0 */
    { PRTA_MixBWColor, TRUE },          /* 1 */
    { PRTA_LeftBorder, 0 },             /* 2 */
    { PRTA_TopBorder,  0 },             /* 3 */
//    { PRTA_ConvertSource, TRUE },       /* 4 */
    { PRTA_ColorCorrection, TRUE },     /* 5 */
    { TAG_END }
};

AROS_PRINTER_TAG(PED, 44, 0,
        .ped_PrinterName = "Skeleton",
        .ped_Init = sk_Init,
        .ped_Expunge = sk_Expunge,
        .ped_Open = sk_Open,
        .ped_Close = sk_Close,

        /* Settings for a 'graphics only' printer */
        .ped_PrinterClass = PPC_COLORGFX | PPCF_EXTENDED,
        .ped_MaxColumns = 0,    /* Set during render */
        .ped_ColorClass = PCC_YMCB | PCC_MULTI_PASS,
        .ped_NumCharSets = 2,
        .ped_NumRows = 1,        /* minimum pixels/row in gfx mode */
        .ped_MaxXDots = 0,       /* Set during render */
        .ped_MaxYDots = 0,       /* Set during render */
        .ped_XDotsInch = 0,      /* Set during render */
        .ped_YDotsInch = 0,      /* Set during render */
        .ped_Commands = (STRPTR *)PED_Commands, /* No ANSI commands */
        .ped_DoSpecial = sk_DoSpecial,
        .ped_Render = sk_Render,
        .ped_TimeoutSecs = 1000, /* For print-to-file timeouts */
        .ped_8BitChars = (STRPTR *)PED_8BitChars,
        .ped_PrintMode = 1,
        .ped_ConvFunc = sk_ConvFunc,
        .ped_TagList = &PED_TagList[0],
        .ped_DoPreferences = sk_DoPreferences,
        .ped_CallErrHook = sk_CallErrHook,
);

struct PrinterData *PD;
static CONST_STRPTR sk_PaperSize;
static LONG sk_PrintBufLen;
static LONG sk_SpacingLPI;
static LONG sk_FontCPI;

static LONG sk_Init(struct PrinterData *pd)
{
    D(bug("sk_Init: pd=%p\n", pd));
    PD = pd;
    return 0;
}

static VOID sk_Expunge(VOID)
{
    D(bug("sk_Expunge\n"));
    PD = NULL;
}

static struct {
    char buff_a[16];
    char buff_b[16];
    char *buff;
    int len;
} sk_PState = {
    .buff = &sk_PState.buff_a[0]
};

#define PFLUSH() do { \
        PD->pd_PWrite(sk_PState.buff, sk_PState.len); \
        if (sk_PState.buff == &sk_PState.buff_a[0]) \
            sk_PState.buff = &sk_PState.buff_b[0]; \
        else \
            sk_PState.buff = &sk_PState.buff_a[0]; \
        sk_PState.len = 0; \
      } while (0)

static AROS_UFH2(void, sk_PPutC,
        AROS_UFHA(UBYTE, c, D0),
        AROS_UFHA(APTR, dummy, A3))
{
    AROS_USERFUNC_INIT

    /* Ignore the trailing 0 that RawDoFmt() tacks on the end */
    if (c == 0)
        return;

    sk_PState.buff[sk_PState.len++]=c;
    if (sk_PState.len >= 16)
        PFLUSH();

    AROS_USERFUNC_EXIT
}

#define sk_PWrite(fmt, ...) \
    do { \
        IPTR args[] = { AROS_PP_VARIADIC_CAST2IPTR(__VA_ARGS__) }; \
        RawDoFmt(fmt, args, (VOID_FUNC)sk_PPutC, NULL); \
        PFLUSH(); \
    } while (0);

#define sk_VWrite(buf, fmt, ...) \
    do { \
        IPTR args[] = { AROS_PP_VARIADIC_CAST2IPTR(__VA_ARGS__) }; \
        RawDoFmt(fmt, args, RAWFMTFUNC_STRING, buf); \
    } while (0);

static LONG sk_Open(union printerIO *ior)
{
    D(bug("sk_Open: ior=%p\n", ior));

    return 0;
}

static VOID sk_Close(union printerIO *ior)
{
    D(bug("sk_Close: ior=%p\n", ior));
}

static LONG sk_RenderInit(struct IODRPReq *io, LONG width, LONG height)
{
    D(bug("sk_RenderInit: Dump raster %ldx%ld pixels, io_RastPort=%p\n", width, height, io->io_RastPort));
    D(bug("\t@%ldx%ld (%ldx%ld) => @%ldx%ld\n", 
           io->io_SrcX, io->io_SrcY, io->io_SrcWidth,
           io->io_SrcHeight, io->io_DestCols, io->io_DestRows));
    LONG alignOffsetX = 0;
    LONG alignOffsetY = 0;
    LONG x, y;

    sk_PrintBufLen = width;
    PD->pd_PrintBuf = AllocMem(sk_PrintBufLen * 6, MEMF_ANY);
    if (PD->pd_PrintBuf == NULL)
        return PDERR_BUFFERMEMORY;

    if (PD->pd_Preferences.PrintFlags & PGFF_CENTER_IMAGE) {
        alignOffsetX = (PED->ped_MaxXDots - width) / 2;
        alignOffsetY = (PED->ped_MaxYDots - height) / 2;
    }

    sk_PWrite("[IMAGE]\n");

    return PDERR_NOERR;
}

static LONG sk_RenderTransfer(struct PrtInfo *pi, LONG color, LONG y)
{
    UBYTE *ptr = PD->pd_PrintBuf;
    union colorEntry *src = pi->pi_ColorInt;
    int x;

    D(bug("\tSource=%p\n", src));

    sk_PWrite("[Image %ld] ", y);
    for (x = 0; x < pi->pi_width; x++, src++, ptr++) {
        *ptr = "  ..ccooCCOO@@##"[(src->colorByte[PCMBLACK] >> 4) & 0xf];
    }

    return PDERR_NOERR;
}

static LONG sk_RenderFlush(LONG rows)
{
    PD->pd_PWrite(PD->pd_PrintBuf, sk_PrintBufLen);
    PD->pd_PWrite("\n", 1);
    return PDERR_NOERR;
}

static LONG sk_RenderClear(void)
{
    memset(PD->pd_PrintBuf, ' ', sk_PrintBufLen);
    return PDERR_NOERR;
}

static LONG sk_RenderPreInit(struct IODRPReq *io, LONG flags)
{
    ULONG dpiX, dpiY;
    ULONG width, height;

    /* Select DPI */
    switch (flags & SPECIAL_DENSITYMASK) {
    case SPECIAL_DENSITY1:
        dpiX = 72;
        dpiY = 72;
        break;
    case SPECIAL_DENSITY2:
        dpiX = 10;
        dpiY = 10;
        break;
    case SPECIAL_DENSITY3:
        dpiX = 120;
        dpiY = 120;
        break;
    case SPECIAL_DENSITY4:
        dpiX = 150;
        dpiY = 150;
        break;
    case SPECIAL_DENSITY5:
        dpiX = 300;
        dpiY = 300;
        break;
    case SPECIAL_DENSITY6:
        dpiX = 600;
        dpiY = 600;
        break;
    case SPECIAL_DENSITY7:
        dpiX = 1200;
        dpiY = 1200;
        break;
    default:
        dpiX = 72;
        dpiY = 72;
    }

    switch (PD->pd_Preferences.PrintPitch) {
    case PP_ELITE: sk_FontCPI = 120; break;
    case PP_FINE:  sk_FontCPI = 171; break;
    case PP_PICA:  sk_FontCPI = 100; break;
    default:
        return PDERR_BADDIMENSION;
    }

    switch (PD->pd_Preferences.PrintSpacing) {
    case PS_SIX_LPI:   sk_SpacingLPI = 6; break;
    case PS_EIGHT_LPI: sk_SpacingLPI = 8; break;
    default:
        return PDERR_BADDIMENSION;
    }

    switch (PD->pd_Preferences.PaperSize) {
/* PaperSize (in units of 0.0001 meters) */
    case US_LETTER: sk_PaperSize = "Letter";  break;   /* 8.5"x11" */
    case US_LEGAL:  sk_PaperSize = "Legal";   break;   /* 8.5"x14" */
    case N_TRACTOR: sk_PaperSize = "80-Col";  break;   /* 9.5"x11" */
    case W_TRACTOR: sk_PaperSize = "132-Col"; break;   /* 14.86"x11" */
/* European sizes */
    case EURO_A0:   sk_PaperSize = "A0";      break;  /* A0: 841 x 1189 */
    case EURO_A1:   sk_PaperSize = "A1";      break;  /* A1: 594 x 841  */
    case EURO_A2:   sk_PaperSize = "A2";      break;  /* A2: 420 x 594  */
    case EURO_A3:   sk_PaperSize = "A3";      break;  /* A3: 297 x 420  */
    case EURO_A4:   sk_PaperSize = "A4";      break;  /* A4: 210 x 297  */
    case EURO_A5:   sk_PaperSize = "A5";      break;  /* A5: 148 x 210  */
    case EURO_A6:   sk_PaperSize = "A6";      break;  /* A6: 105 x 148  */
    case EURO_A7:   sk_PaperSize = "A7";      break;  /* A7: 74 x 105   */
    case EURO_A8:   sk_PaperSize = "A8";      break;  /* A8: 52 x 74    */
    case CUSTOM:    sk_PaperSize = "Custom";  break;
    default:        return PDERR_BADDIMENSION;
    }

    /* Set up for the page size */
    switch (PD->pd_Preferences.PaperSize) {
/* PaperSize (in units of 0.0001 meters) */
    case US_LETTER: width = 2159; height = 2794; break;   /* 8.5"x11" */
    case US_LEGAL:  width = 2159; height = 3556; break;   /* 8.5"x14" */
    case N_TRACTOR: width = 2413; height = 2794; break;   /* 9.5"x11" */
    case W_TRACTOR: width = 3774; height = 2794; break;   /* 14.86"x11" */
/* European sizes */
    case EURO_A0:   width = 8410; height = 11890; break;  /* A0: 841 x 1189 */
    case EURO_A1:   width = 5940; height =  8410; break;  /* A1: 594 x 841  */
    case EURO_A2:   width = 4200; height =  5940; break;  /* A2: 420 x 594  */
    case EURO_A3:   width = 2970; height =  4200; break;  /* A3: 297 x 420  */
    case EURO_A4:   width = 2100; height =  2970; break;  /* A4: 210 x 297  */
    case EURO_A5:   width = 1480; height =  2100; break;  /* A5: 148 x 210  */
    case EURO_A6:   width = 1050; height =  1480; break;  /* A6: 105 x 148  */
    case EURO_A7:   width =  740; height =  1050; break;  /* A7: 74 x 105   */
    case EURO_A8:   width =  520; height =   740; break;  /* A8: 52 x 74    */
    case CUSTOM:    width  = PD->pd_Preferences.PrintMaxWidth * 254 / 10;
                    height = PD->pd_Preferences.PrintMaxHeight * 254 / 10;
                    break;
    default:        return PDERR_CANCEL;
    }

    PED->ped_MaxColumns = width * sk_FontCPI / 2540;
    PED->ped_XDotsInch = dpiX;
    PED->ped_YDotsInch = dpiY;
    PED->ped_MaxXDots = width * dpiX / 254;
    PED->ped_MaxYDots = height * dpiY / 254;
D(bug("MaxColumns=%d, dpiX=%d, dpiY=%d, MaxXDots=%d, MaxYDots=%d (%d x %d in)\n",
        PED->ped_MaxColumns, PED->ped_XDotsInch, PED->ped_YDotsInch,
        PED->ped_MaxXDots, PED->ped_MaxYDots,
        PED->ped_MaxXDots / dpiX, PED->ped_MaxYDots / dpiY));

    return PDERR_NOERR;
}

static LONG sk_RenderClose(SIPTR error, ULONG flags)
{
    if (error != PDERR_CANCEL) {
        /* Send formfeed */
        if (!(flags & SPECIAL_NOFORMFEED))
            sk_PWrite("[FF]\n");
    }

    sk_PWrite("[Close]\n");

    return PDERR_NOERR;
}

static LONG sk_RenderNextColor(void)
{
    return PDERR_NOERR;
}
    
/* If Tag PRTA_ConvertSource is set, this function is called instead
 * of the printer.device built-in to convert.
 *
 * The size of each entry is either sizeof(union colorEntry), or
 * Tag PRTA_ColorSize (if set)
 *
 * The conversion is done in-place.
 */
static LONG sk_RenderConvert(APTR row, LONG entries, LONG is_pixels)
{
    return PDERR_NOERR;
}

/* If Tag PRTA_ColorCorrection is set, this function is called instead
 * of the printer.device built-in to correct printer-space colors.
 *
 * The size of each entry is either sizeof(union colorEntry), or
 * Tag PRTA_ColorSize (if set)
 *
 * The conversion is done in-place.
 */
static LONG sk_RenderCorrect(APTR row, LONG entries, LONG is_pixels)
{
    return PDERR_NOERR;
}

static LONG sk_Render(SIPTR ct, LONG x, LONG y, LONG status)
{
    LONG err = PDERR_NOERR;

    switch (status) {
    case PRS_INIT:
        D(bug("PRS_INIT: IODRPReq=%p, width=%d, height=%d\n", ct, x, y));
        err = sk_RenderInit((struct IODRPReq *)ct, x, y);
        break;
    case PRS_TRANSFER:
        D(bug("PRS_TRANSFER: PrtInfo=%p, color=%d, row=%d\n", ct, x, y));
        err = sk_RenderTransfer((struct PrtInfo *)ct, x, y);
        break;
    case PRS_FLUSH:
        D(bug("PRS_FLUSH: ct=%p, x=%d, rows=%d\n", ct, x, y));
        err = sk_RenderFlush(y);
        break;
    case PRS_CLEAR:
        D(bug("PRS_CLEAR: ct=%p, x=%d, y=%d\n", ct, x, y));
        err = sk_RenderClear();
        break;
    case PRS_CLOSE:
        D(bug("PRS_CLOSE: error=%d, io_Special=0x%0x, y=%d\n", ct, x, y));
        err = sk_RenderClose(ct, x);
        break;
    case PRS_PREINIT:
        D(bug("PRS_PREINIT: IODRPReq=%p, io_Special=0x%0x, y=%d\n", ct, x, y));
        err = sk_RenderPreInit((struct IODRPReq *)ct, x);
        break;
    case PRS_NEXTCOLOR:
        D(bug("PRS_NEXTCOLOR: ct=%p, x=0x%0x, y=%d\n", ct, x, y));
        err = sk_RenderNextColor();
        break;
    case PRS_UNKNOWN:
        D(bug("PRS_UNKNOWN: ct=%p, x=0x%0x, y=%d\n", ct, x, y));
        err = PDERR_NOERR;
        break;
    case PRS_CONVERT:
        D(bug("PRS_CONVERT: row=%p, entries=%d, type=%s\n", ct, x, y ? "pixels" : "union colorEntry"));
        err = sk_RenderConvert((APTR)ct, x, y);
        break;
    case PRS_CORRECT:
        D(bug("PRS_CORRECT: row=%p, entries=%d, type=%s\n", ct, x, y ? "pixels" : "union colorEntry"));
        err = sk_RenderCorrect((APTR)ct, x, y);
        break;
    default:
        D(bug("PRS_xxxx(%d): ct=%p, x=0x%0x, y=%d\n", status, ct, x, y));
        break;
    }
        
    return err;
}

/* Text output:
 *  > 0 = processed, add N chars
 *  0   = not handled by DoSpecial
 *  -1  = Unsupported command
 *  -2  = Processed, but no additional chars in the buffer
 */
static LONG sk_DoSpecial(UWORD *command, UBYTE output_buffer[],
                         BYTE *current_line_position,
                         BYTE *current_line_spacing,
                         BYTE *crlf_flag, UBYTE params[])
{
    D(bug("sk_DoSpecial: command=0x%04x, output_buffer=%p, current_line_position=%d, current_line_spacing=%d, crlf_flag=%d, params=%s\n",
                *command, output_buffer,  *current_line_position, *current_line_spacing, *crlf_flag, params));

    sk_VWrite(output_buffer, "[%s %ld,%ld,%ld,%ld]", cmdTable[*command], params[0], params[1], params[2], params[3]);

    return strlen(output_buffer);
}

static LONG sk_ConvFunc(UBYTE *buf, UBYTE c, LONG crlf_flag)
{
    D(bug("sk_ConvFunc: %p '%c' %d\n", buf, c, crlf_flag));

    /* NOTE: For compatability with AOS 3.x, do 
     *       not attempt to convert ESC or \377
     *       characters if you want DoSpecial() to work.
     */
    if (c == 0x1b || c == 0xff)
        return -1;

    /* As a demo, we're going to UPPERCASE all characters,
     * and put a '\' in front of the modified character.
     */
    if (c >= 'a' && c <= 'z') {
        *(buf++) = '\\';
        *(buf++) = c;
        return 2;
    }

    return -1;
}

static LONG sk_DoPreferences(union printerIO *ior, LONG command)
{
    D(bug("sk_DoPreferences: ior=%p, command=%d\n"));
    return 0;
}

static VOID sk_CallErrHook(union printerIO *ior, struct Hook *hook)
{
    D(bug("sk_CallErrHook: ior=%p, hook=%p\n", ior, hook));
}

參考文獻

[編輯 | 編輯原始碼]
 struct FileHandle *file;

    file = Open( "PRT:", MODE_NEWFILE ); /* Open PRT: */
    if (file == 0)                       /* if the open was unsuccessful */
        exit(PRINTER_WONT_OPEN);

參見 2View src

閱讀更多關於 印表機驅動程式 和更多 印表機驅動程式

還可以看一下 TurboPrint 的 printer.device API 擴充套件。在 v44 之前,它一直是多年來的事實標準。可以在 此處找到文件。實際上,AROS printer.device 已經支援所有 CyberGfx 點陣圖格式以及每種螢幕模式。當然。但 TurboPrint 還用自己的命令擴充套件了 printer.device。如果您對 68k 二進位制相容性感興趣,這可能是一個簡單的補充,因為它非常接近 CBM 的 DUMPRPORT 命令。

它的工作原理是將所有縮放比例放到源點陣圖的 AllocBitmap()“朋友”中,並使用 CyberGfx ReadPixelArray() 從中獲取 BGR032 畫素行。BGR032 與印表機驅動程式內部使用的格式相同(除非為 YMCK 目的而反轉),因此無需在那裡進行額外的轉換。io_Modes 僅用於獲取顯示器的縱橫比。我還沒有測試過列印 HAM6 或 HAM8 影像,但我也不知道是否有用於此的測試程式。我建議使用 Turboprint SDK 和 Ghostscript 68k(舊的 5.x,包含在 TurboPrint 中,以及新的)中的示例程式。兩者都提供原始碼。ArtEffect 也支援 Turboprint,還有我的 Scandal(aros x86 版本也是如此,但您必須有一些支援的掃描器才能獲取要列印的資料 :))

commit 43799 重新結構化以允許未來的印表機驅動程式。

    struct IODRPReq
    {
        struct  Message io_Message;
        struct  Device  *io_Device;     /* device node pointer  */
        struct  Unit    *io_Unit;       /* unit (driver private)*/
        UWORD   io_Command;             /* device command */
        UBYTE   io_Flags;
        BYTE    io_Error;               /* error or warning num */
        struct  RastPort *io_RastPort;  /* raster port */
        struct  ColorMap *io_ColorMap;  /* color map */
        ULONG   io_Modes;               /* graphics viewport modes */
        UWORD   io_SrcX;                /* source x origin */
        UWORD   io_SrcY;                /* source y origin */
        UWORD   io_SrcWidth;            /* source x width */
        UWORD   io_SrcHeight;           /* source x height */
        LONG    io_DestCols;            /* destination x width */
        LONG    io_DestRows;            /* destination y height */
        UWORD   io_Special;             /* option flags */
    };
    struct IOPrtCmdReq
    {
        struct  Message io_Message;
        struct  Device  *io_Device;     /* device node pointer  */
        struct  Unit    *io_Unit;       /* unit (driver private)*/
        UWORD   io_Command;             /* device command */
        UBYTE   io_Flags;
        BYTE    io_Error;               /* error or warning num */
        UWORD   io_PrtCommand;          /* printer command */
        UBYTE   io_Parm0;               /* first command parameter */
        UBYTE   io_Parm1;               /* second command parameter */
        UBYTE   io_Parm2;               /* third command parameter */
        UBYTE   io_Parm3;               /* fourth command parameter */
    };

錯誤在 io_Error 中找到。

                  PRINTER DEVICE ERROR CODES

   Error                   Value Explanation
   -----                   ----- -----------
   PDERR_NOERR               0   Operation successful
   PDERR_CANCEL              1   User canceled request
   PDERR_NOTGRAPHICS         2   Printer cannot output graphics
   PDERR_INVERTHAM           3   OBSOLETE
   PDERR_BADDIMENSION        4   Print dimensions are illegal
   PDERR_DIMENSIONOVERFLOW   5   OBSOLETE
   PDERR_INTERNALMEMORY      6   No memory available for internal variables
   PDERR_BUFFERMEMORY        7   No memory available for print buffer

                      EXEC ERROR CODES

   Error                   Value Explanation
   ----                    ----- -----------
   IOERR_OPENFAIL           -1   Device failed to open
   IOERR_ABORTED            -2   Request terminated early (after AbortIO())
   IOERR_NOCMD              -3   Command not supported by device
   IOERR_BADLENGTH          -4   Not a valid length
Amiga Printer Commands
----------------------

 Esc[<n>"<x>

where `<n>' is the decimal typed number of bytes in the string `<x>', which actually contains your special printer sequence. This ANSI sequence tells the printer driver to not interpret or translate the next `<n>' bytes.

10    Line Feed
13    Carriage Return
14    Form Feed

ESCc 	Reset
ESC#1	Initialise
ESCD	Line feed
ESCE	CR, LF
ESCM	Reverse line feed
ESC[0m	Normal char set
ESC[3m	Italics on
ESC[23m Italics off
ESC[4m	Underline on
ESC[24m	Underline off
ESC[1m  Bold on
ESC[22	Boldface off

ESC[nm  Set foreground colour (30-39)
ESC[nm  Set background colour (40-49)

ESC[0w	Normal pitch
ESC[2w	Elite on
ESC[1w	Elite off
ESC[4w	Condensed on
ESC[3w	Condensed off
ESC[6w	Enlarge on
ESC[5w	Enlarge off
ESC[6"z Shadow print on
ESC[5"z Shadow print off
ESC[4"z Doublestrikes on
ESC[3"z Doublestrikes off
ESC[2"z NLQ on
ESC[1"z NLQ off
ESC[2v  Superscript on
ESC[1v	Superscript off
ESC[4v	Subscript on
ESC[3v  Subscript off
ESC[0v  Normalise the line
ESCL	Partial line up
ESCK	Partial line down

ESC(B	US Char set     (Typeface 0)
ESC(R	French char set (Typeface 1)
ESC(K	German char set (Typeface 2)
ESC(A	UK char set     (Typeface 3)
ESC(E	Danish 1 char set (Typeface 4)
ESC(H	Swedish char set (Typeface 5)
ESC(Y	Italian char set (Typeface 6)
ESC(Z	Spanish char set (Typeface 7)
ESC(J	Japanese char set  (Typeface 8)
ESC(6 	Norwegian char set (Typeface 90)
ESC(C	Danish 2 char set  (Typeface 10)

ESC[2p	Proportional on
ESC[1p	Proportional off
ESC[0p  Proportional clear
ESC[nE  Set proportional offset
ESC[5F	Auto left justify
ESC[7F	Auto right justify
ESC[6F	Auto full justify
ESC[0F	Auto justify off
ESC[3F	Letter space (justify)
ESC[1F	Word fill (Auto Centre)
ESC[0z	1/8" line spacing
ESC[1z	1/6" line spacing
ESC[nt	Set form length n
ESC[nq	Perforation skip n (n>0)
ESC[0q	Perforation skip off

ESC#9	Set left margin
ESC#0	Set right margin
ESC#8	Set top margin
ESC#2	Set bottom margin
ESC[n;nr Top and bottom margins
ESC[n;ns Left and right margins
ESC#3	Clear margins
ESCH	Set horizontal tab
ESCJ	Setg Vertical tab
ESC[0g	Clear horizontal tab
ESC[3g	Clear all horizontal tabs
ESC[1g	Clear Vertical tab
ESC[4g  Clear all vertical tabs
ESC#4	Clear all tabs
ESC#5	Set default tabs
ESC[n"x Extended commands

n = Decimal number e.g. 12
                     PRINTER DEVICE COMMAND FUNCTIONS

           Cmd     Escape                                          Defined
   Name    No.     Sequence   Function                               by:
   ----    ---     --------   --------                             -------
   aRIS    0       ESCc       Reset                                ISO
   aRIN    1       ESC#1      Initialize                           +++
   aIND    2       ESCD       Linefeed                             ISO
   aNEL    3       ESCE       Return,linefeed                      ISO
   aRI     4       ESCM       Reverse linefeed                     ISO
   aSGR0   5       ESC[0m     Normal char set                      ISO
   aSGR3   6       ESC[3m     Italics on                           ISO
   aSGR23  7       ESC[23m    Italics off                          ISO
   aSGR4   8       ESC[4m     Underline on                         ISO
   aSGR24  9       ESC[24m    Underline off                        ISO
   aSGR1   10      ESC[1m     Boldface on                          ISO
   aSGR22  11      ESC[22m    Boldface off                         ISO
   aSFC    12      ESC[nm     Set foreground color where n         ISO
                              stands for a pair of ASCII digits,
                              3 followed by any number 0-9
                              (See ISOColor Table)

   aSBC    13      ESC[nm     Set background color where n         ISO
                              stands for a pair of ASCII digits,
                              4 followed by any number 0-9
                              (See ISO Color Table)

   aSHORP0 14      ESC[0w     Normal pitch                         DEC
   aSHORP2 15      ESC[2w     Elite on                             DEC
   aSHORP1 16      ESC[1w     Elite off                            DEC
   aSHORP4 17      ESC[4w     Condensed fine on                    DEC
   aSHORP3 18      ESC[3w     Condensed off                        DEC
   aSHORP6 19      ESC[6w     Enlarged on                          DEC
   aSHORP5 20      ESC[5w     Enlarged off                         DEC
   aDEN6   21      ESC[6"z    Shadow print on                      DEC
   aDEN5   22      ESC[5"z    Shadow print off            (sort of)DEC
   aDEN4   23      ESC[4"z    Doublestrike on                      DEC
   aDEN3   24      ESC[3"z    Doublestrike off                     DEC
   aDEN2   25      ESC[2"z    NLQ on                               DEC
   aDEN1   26      ESC[1"z    NLQ off                              DEC

   aSUS2   27      ESC[2v     Superscript on                       +++
   aSUS1   28      ESC[1v     Superscript off                      +++
   aSUS4   29      ESC[4v     Subscript on                         +++
   aSUS3   30      ESC[3v     Subscript off                        +++
   aSUS0   31      ESC[0v     Normalize the line                   +++
   aPLU    32      ESCL       Partial line up                      ISO
   aPLD    33      ESCK       Partial line down                    ISO

   aFNT0   34      ESC(B      US char set or Typeface 0            DEC
   aFNT1   35      ESC(R      French char set or Typeface 1        DEC
   aFNT2   36      ESC(K      German char set or Typeface 2        DEC
   aFNT3   37      ESC(A      UK char set or Typeface 3            DEC
   aFNT4   38      ESC(E      Danish I char set or Typeface 4      DEC
   aFNT5   39      ESC(H      Swedish char set or Typeface 5       DEC
   aFNT6   40      ESC(Y      Italian char set or Typeface 6       DEC
   aFNT7   41      ESC(Z      Spanish char set or Typeface 7       DEC
   aFNT8   42      ESC(J      Japanese char set or Typeface 8      +++
   aFNT9   43      ESC(6      Norwegian char set or Typeface 9     DEC
   aFNT10  44      ESC(C      Danish II char set or Typeface 10    +++
                              (See Suggested Typefaces Table)

   aPROP2  45      ESC[2p     Proportional on                      +++
   aPROP1  46      ESC[1p     Proportional off                     +++
   aPROP0  47      ESC[0p     Proportional clear                   +++
   aTSS    48      ESC[n E    Set proportional offset              ISO
   aJFY5   49      ESC[5 F    Auto left justify                    ISO
   aJFY7   50      ESC[7 F    Auto right justify                   ISO
   aJFY6   51      ESC[6 F    Auto full justify                    ISO
   aJFY0   52      ESC[0 F    Auto justify off                     ISO
   aJFY3   53      ESC[3 F    Letter space (justify)      (special)ISO
   aJFY1   54      ESC[1 F    Word fill(auto center)      (special)ISO

   aVERP0  55      ESC[0z     1/8" line spacing                    +++
   aVERP1  56      ESC[1z     1/6" line spacing                    +++
   aSLPP   57      ESC[nt     Set form length n                    DEC
   aPERF   58      ESC[nq     Perf skip n (n>0)                    +++
   aPERF0  59      ESC[0q     Perf skip off                        +++

   aLMS    60      ESC#9      Left margin set                      +++
   aRMS    61      ESC#0      Right margin set                     +++
   aTMS    62      ESC#8      Top margin set                       +++
   aBMS    63      ESC#2      Bottom margin set                    +++
   aSTBM   64      ESC[n;     nr Top and bottom margins            DEC
   aSLRM   65      ESC[n;     ns Left and right margins DEC
   aCAM    66      ESC#3      Clear margins +++

   aHTS    67      ESCH       Set horizontal tab                   ISO
   aVTS    68      ESCJ       Set vertical tabs                    ISO
   aTBC0   69      ESC[0g     Clear horizontal tab                 ISO
   aTBC3   70      ESC[3g     Clear all h. tabs                    ISO
   aTBC1   71      ESC[1g     Clear vertical tab                   ISO
   aTBC4   72      ESC[4g     Clear all v. tabs                    ISO
   aTBCALL 73      ESC#4      Clear all h. & v. tabs               +++
   aTBSALL 74      ESC#5      Set default tabs                     +++
   aEXTEND 75      ESC[n"x    Extended commands                    +++

   aRAW    76      ESC[n"r    Next n chars are raw                 +++

   Legend:
   ------
   ISO     indicates that the sequence has been defined by the
           International Standards Organization.  This is
           also very similar to ANSI x3.64.

   DEC     indicates a control sequence defined by Digital Equipment
           Corporation.

   +++     indicates a sequence unique to Amiga.

   n       stands for a decimal number expressed as a set of ASCII
           digits. In the aRAW string ESC[5"rHELLO, n is substituted by 5,
           the number of RAW characters you send to the printer.

           ISO Color Table            Suggested Typefaces
           ---------------            -------------------
           0  Black                   0   Default typeface
           1  Red                     1   Line Printer or equivalent
           2  Green                   2   Pica or equivalent
           3  Yellow                  3   Elite or equivalent
           4  Blue                    4   Helvetica or equivalent
           5  Magenta                 5   Times Roman or equivalent
           6  Cyan                    6   Gothic or equivalent
           7  White                   7   Script or equivalent
           8  NC                      8   Prestige or equivalent
           9  Default                 9   Caslon or equivalent
                                      10  Orator or equivalent

The status is returned in the two UBYTES set in the io_Data field.  The
printer type, either serial or parallel, is returned in the io_Actual
field.

   io_Data         Bit     Active          Function (Serial Device)
   -------         ---     ------          ------------------------
     LSB           0       low             reserved
                   1       low             reserved
                   2       low             reserved
                   3       low             Data Set Ready
                   4       low             Clear To Send
                   5       low             Carrier Detect
                   6       low             Ready To Send
                   7       low             Data Terminal Ready
     MSB           8       high            read buffer overflow
                   9       high            break sent (most recent output)
                   10      high            break received (as latest input)
                   11      high            transmit x-OFFed
                   12      high            receive x-OFFed
                   13-15   high            reserved

   io_Data         Bit     Active          Function (Parallel Device)
   -------         ---     ------          --------------------------
     LSB           0       high            printer busy (offline)
                   1       high            paper out
                   2       high            printer selected
                   3        -              read=0; write=1
                   4-7                     reserved
     MSB           8-15                    reserved

   io_Actual                               1-parallel, 2-serial
PIO->iodrp.io_Special = SPECIAL_ASPECT | SPECIAL_FRACCOLS;
PIO->iodrp.io_DestCols = 0xffffffff / 2;
PIO->iodrp.io_DestRows = 0;
華夏公益教科書