134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 2d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang// Process IPTC data and XMP data. 334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include "jhead.h" 534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang// IPTC entry types known to Jhead (there's many more defined) 7d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define IPTC_RECORD_VERSION 0x00 834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_SUPLEMENTAL_CATEGORIES 0x14 934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_KEYWORDS 0x19 1034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_CAPTION 0x78 1134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_AUTHOR 0x7A 1234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_HEADLINE 0x69 1334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_SPECIAL_INSTRUCTIONS 0x28 1434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_CATEGORY 0x0F 1534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_BYLINE 0x50 1634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_BYLINE_TITLE 0x55 1734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_CREDIT 0x6E 1834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_SOURCE 0x73 1934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_COPYRIGHT_NOTICE 0x74 2034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_OBJECT_NAME 0x05 2134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_CITY 0x5A 2234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_STATE 0x5F 2334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_COUNTRY 0x65 2434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_TRANSMISSION_REFERENCE 0x67 2534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_DATE 0x37 2634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_COPYRIGHT 0x0A 2734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_COUNTRY_CODE 0x64 2834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define IPTC_REFERENCE_SERVICE 0x2D 29d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define IPTC_TIME_CREATED 0x3C 30d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define IPTC_SUB_LOCATION 0x5C 31d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define IPTC_IMAGE_TYPE 0x82 3234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 3334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 3434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Process and display IPTC marker. 3534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 3634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// IPTC block consists of: 3734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - Marker: 1 byte (0xED) 3834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - Block length: 2 bytes 3934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - IPTC Signature: 14 bytes ("Photoshop 3.0\0") 4034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - 8BIM Signature 4 bytes ("8BIM") 4134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - IPTC Block start 2 bytes (0x04, 0x04) 4234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - IPTC Header length 1 byte 4334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - IPTC header Header is padded to even length, counting the length byte 4434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - Length 4 bytes 4534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - IPTC Data which consists of a number of entries, each of which has the following format: 4634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - Signature 2 bytes (0x1C02) 4734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - Entry type 1 byte (for defined entry types, see #defines above) 4834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - entry length 2 bytes 4934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// - entry data 'entry length' bytes 5034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 5134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 5234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid show_IPTC (unsigned char* Data, unsigned int itemlen) 5334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 5434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char IptcSig1[] = "Photoshop 3.0"; 5534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char IptcSig2[] = "8BIM"; 5634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const char IptcSig3[] = {0x04, 0x04}; 5734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * pos = Data + sizeof(short); // position data pointer after length field 5934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * maxpos = Data+itemlen; 6034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char headerLen = 0; 6134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (itemlen < 25) goto corrupt; 6334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Check IPTC signatures 6534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (memcmp(pos, IptcSig1, sizeof(IptcSig1)-1) != 0) goto badsig; 6634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project pos += sizeof(IptcSig1); // move data pointer to the next field 6734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (memcmp(pos, IptcSig2, sizeof(IptcSig2)-1) != 0) goto badsig; 6934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project pos += sizeof(IptcSig2)-1; // move data pointer to the next field 7034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 7134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (memcmp(pos, IptcSig3, sizeof(IptcSig3)) != 0){ 7234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectbadsig: 7334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags){ 7434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("IPTC type signature mismatch\n",0,0); 7534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 7634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 7734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 7834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project pos += sizeof(IptcSig3); // move data pointer to the next field 7934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (pos >= maxpos) goto corrupt; 8134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // IPTC section found 8334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Skip header 8534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project headerLen = *pos++; // get header length and move data pointer to the next field 8634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project pos += headerLen + 1 - (headerLen % 2); // move data pointer to the next field (Header is padded to even length, counting the length byte) 8734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (pos+4 >= maxpos) goto corrupt; 8934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 9034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Get length (from motorola format) 9134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project //length = (*pos << 24) | (*(pos+1) << 16) | (*(pos+2) << 8) | *(pos+3); 9234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 93d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang pos += 4; // move data pointer to the next field 9434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 9534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("======= IPTC data: =======\n"); 9634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 9734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Now read IPTC data 9834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project while (pos < (Data + itemlen-5)) { 9934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project short signature; 100d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang unsigned char type = 0; 10134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project short length = 0; 10234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char * description = NULL; 10334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 10434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (pos+5 > maxpos) goto corrupt; 10534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 10634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project signature = (*pos << 8) + (*(pos+1)); 107d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang pos += 2; 10834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 10934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (signature != 0x1C02){ 11034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 11134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 11234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 11334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project type = *pos++; 11434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project length = (*pos << 8) + (*(pos+1)); 115d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang pos += 2; // Skip tag length 11634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 11734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (pos+length > maxpos) goto corrupt; 11834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Process tag here 11934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch (type) { 120d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case IPTC_RECORD_VERSION: 121d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("Record vers. : %d\n", (*pos << 8) + (*(pos+1))); 122d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang break; 123d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 12434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_SUPLEMENTAL_CATEGORIES: description = "SuplementalCategories"; break; 12534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_KEYWORDS: description = "Keywords"; break; 12634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_CAPTION: description = "Caption"; break; 12734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_AUTHOR: description = "Author"; break; 12834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_HEADLINE: description = "Headline"; break; 129d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case IPTC_SPECIAL_INSTRUCTIONS: description = "Spec. Instr."; break; 13034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_CATEGORY: description = "Category"; break; 13134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_BYLINE: description = "Byline"; break; 132d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case IPTC_BYLINE_TITLE: description = "Byline Title"; break; 13334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_CREDIT: description = "Credit"; break; 13434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_SOURCE: description = "Source"; break; 13534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_COPYRIGHT_NOTICE: description = "(C)Notice"; break; 136d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case IPTC_OBJECT_NAME: description = "Object Name"; break; 13734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_CITY: description = "City"; break; 13834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_STATE: description = "State"; break; 13934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_COUNTRY: description = "Country"; break; 14034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_TRANSMISSION_REFERENCE: description = "OriginalTransmissionReference"; break; 14134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_DATE: description = "DateCreated"; break; 14234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case IPTC_COPYRIGHT: description = "(C)Flag"; break; 143d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case IPTC_REFERENCE_SERVICE: description = "Country Code"; break; 144d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case IPTC_COUNTRY_CODE: description = "Ref. Service"; break; 145d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case IPTC_TIME_CREATED: description = "Time Created"; break; 146d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case IPTC_SUB_LOCATION: description = "Sub Location"; break; 147d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case IPTC_IMAGE_TYPE: description = "Image type"; break; 148d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 14934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project default: 15034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags){ 151d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("Unrecognised IPTC tag: %d\n", type ); 15234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 15334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 15434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 15534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (description != NULL) { 15634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char TempBuf[32]; 15734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memset(TempBuf, 0, sizeof(TempBuf)); 158d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang memset(TempBuf, ' ', 14); 15934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(TempBuf, description, strlen(description)); 16034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strcat(TempBuf, ":"); 16134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("%s %*.*s\n", TempBuf, length, length, pos); 16234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 16334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project pos += length; 16434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 16534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 16634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectcorrupt: 16734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Pointer corruption in IPTC\n",0,0); 16834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 169d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 170d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 171d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 172d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang//-------------------------------------------------------------------------- 173d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang// Dump contents of XMP section 174d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang//-------------------------------------------------------------------------- 175d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Changvoid ShowXmp(Section_t XmpSection) 176d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang{ 177d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang unsigned char * Data; 178d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang char OutLine[101]; 179d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang int OutLineChars; 180d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang int NonBlank; 181d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang unsigned a; 182d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang NonBlank = 0; 183d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang Data = XmpSection.Data; 184d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang OutLineChars = 0; 185d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 186d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 187d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang for (a=0;a<XmpSection.Size;a++){ 188d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (Data[a] >= 32 && Data[a] < 128){ 189d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang OutLine[OutLineChars++] = Data[a]; 190d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (Data[a] != ' ') NonBlank |= 1; 191d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang }else{ 192d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (Data[a] != '\n'){ 193d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang OutLine[OutLineChars++] = '?'; 194d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 195d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 196d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (Data[a] == '\n' || OutLineChars >= 100){ 197d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang OutLine[OutLineChars] = 0; 198d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (NonBlank){ 199d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang puts(OutLine); 200d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 201d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang NonBlank = (NonBlank & 1) << 1; 202d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang OutLineChars = 0; 203d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 204d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 205d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang} 206