Resource::DataStreamPtr ResourceManager::CreateDataStream(const String& AssetName, const String& AssetGroup, void* Buffer, const UInt32 BufferSize) { Resource::DataStreamPtr NewStream( new Resource::MemoryStream(Buffer,BufferSize,true) ); /// @todo Once we have our own AssetGroup implementation we need to implement this. MEZZ_EXCEPTION(Exception::NOT_IMPLEMENTED_EXCEPTION,"Assigning new DataStreams to AssetGroups has not yet been implemented."); return NewStream; }
static Stream *ReadFile(FILE *fin) { int c; Stream *in = NewStream(fin); while ((c = ReadChar(in)) >= 0) AddByte(in, (uint)c); return in; }
static void HailExec(AgentConnection *conn, char *peer, char *recvbuffer, char *sendbuffer) { FILE *fp = stdout; char *sp; int n_read; if (strlen(DEFINECLASSES)) { snprintf(sendbuffer, CF_BUFSIZE, "EXEC %s -D%s", REMOTE_AGENT_OPTIONS, DEFINECLASSES); } else { snprintf(sendbuffer, CF_BUFSIZE, "EXEC %s", REMOTE_AGENT_OPTIONS); } if (SendTransaction(conn->sd, sendbuffer, 0, CF_DONE) == -1) { CfOut(cf_error, "send", "Transmission rejected"); DisconnectServer(conn); return; } fp = NewStream(peer); SendClassData(conn); while (true) { memset(recvbuffer, 0, CF_BUFSIZE); if ((n_read = ReceiveTransaction(conn->sd, recvbuffer, NULL)) == -1) { return; } if (n_read == 0) { break; } if (strlen(recvbuffer) == 0) { continue; } if ((sp = strstr(recvbuffer, CFD_TERMINATOR)) != NULL) { fprintf(fp, "%s> !!\n\n", VPREFIX); break; } if ((sp = strstr(recvbuffer, "BAD:")) != NULL) { fprintf(fp, "%s> !! %s\n", VPREFIX, recvbuffer + 4); continue; } if (strstr(recvbuffer, "too soon")) { fprintf(fp, "%s> !! %s\n", VPREFIX, recvbuffer); continue; } fprintf(fp, "%s> -> %s", VPREFIX, recvbuffer); } DeleteStream(fp); DisconnectServer(conn); }
Int StartChildProcess ( Char *dir, Char *prg, Char *args[] ) { /* Int j; / loop variables */ /* char c[8]; / buffer for communication */ /* int n; / return value of 'select' */ int slave; /* pipe to child */ Int stream; #if HAVE_TERMIOS_H struct termios tst; /* old and new terminal state */ #elif HAVE_TERMIO_H struct termio tst; /* old and new terminal state */ #elif HAVE_SGTTY_H struct sgttyb tst; /* old and new terminal state */ #elif !defined(USE_PRECOMPILED) /* If no way to store and reset terminal states is known, and we are not currently re-making the dependency list (via cnf/Makefile), then trigger an error. */ #error No supported way of (re)storing terminal state is available #endif /* Get a stream record */ stream = NewStream(); if (stream == -1) return -1; /* open pseudo terminal for communication with gap */ if ( OpenPty(&PtyIOStreams[stream].ptyFD, &slave) ) { Pr( "open pseudo tty failed\n", 0L, 0L); FreeStream(stream); return -1; } /* Now fiddle with the terminal sessions on the pty */ #if HAVE_TERMIOS_H if ( tcgetattr( slave, &tst ) == -1 ) { Pr( "tcgetattr on slave pty failed\n", 0L, 0L); goto cleanup; } tst.c_cc[VINTR] = 0377; tst.c_cc[VQUIT] = 0377; tst.c_iflag &= ~(INLCR|ICRNL); tst.c_cc[VMIN] = 1; tst.c_cc[VTIME] = 0; tst.c_lflag &= ~(ECHO|ICANON); tst.c_oflag &= ~(ONLCR); if ( tcsetattr( slave, TCSANOW, &tst ) == -1 ) { Pr("tcsetattr on slave pty failed\n", 0, 0 ); goto cleanup; } #elif HAVE_TERMIO_H if ( ioctl( slave, TCGETA, &tst ) == -1 ) { Pr( "ioctl TCGETA on slave pty failed\n"); goto cleanup; } tst.c_cc[VINTR] = 0377; tst.c_cc[VQUIT] = 0377; tst.c_iflag &= ~(INLCR|ICRNL); tst.c_cc[VMIN] = 1; tst.c_cc[VTIME] = 0; /* Note that this is at least on Linux dangerous! Therefore, we now have the HAVE_TERMIOS_H section for POSIX Terminal control. */ tst.c_lflag &= ~(ECHO|ICANON); if ( ioctl( slave, TCSETAW, &tst ) == -1 ) { Pr( "ioctl TCSETAW on slave pty failed\n"); goto cleanup; } #elif HAVE_SGTTY_H if ( ioctl( slave, TIOCGETP, (char*)&tst ) == -1 ) { Pr( "ioctl TIOCGETP on slave pty failed\n"); goto cleanup; } tst.sg_flags |= RAW; tst.sg_flags &= ~ECHO; if ( ioctl( slave, TIOCSETN, (char*)&tst ) == -1 ) { Pr( "ioctl on TIOCSETN slave pty failed\n"); goto cleanup; } #endif /* set input to non blocking operation */ /* Not any more */ PtyIOStreams[stream].inuse = 1; PtyIOStreams[stream].alive = 1; PtyIOStreams[stream].blocked = 0; PtyIOStreams[stream].changed = 0; /* fork */ PtyIOStreams[stream].childPID = fork(); if ( PtyIOStreams[stream].childPID == 0 ) { /* Set up the child */ close(PtyIOStreams[stream].ptyFD); if ( dup2( slave, 0 ) == -1) _exit(-1); fcntl( 0, F_SETFD, 0 ); if (dup2( slave, 1 ) == -1) _exit(-1); fcntl( 1, F_SETFD, 0 ); if ( chdir(dir) == -1 ) { _exit(-1); } #if HAVE_SETPGID setpgid(0,0); #endif execv( prg, args ); /* This should never happen */ close(slave); _exit(1); } /* Now we're back in the master */ /* check if the fork was successful */ if ( PtyIOStreams[stream].childPID == -1 ) { Pr( "Panic: cannot fork to subprocess.\n", 0, 0); goto cleanup; } close(slave); return stream; cleanup: close(slave); close(PtyIOStreams[stream].ptyFD); PtyIOStreams[stream].inuse = 0; FreeStream(stream); return -1; }
Resource::DataStreamPtr ResourceManager::CreateDataStream(void* Buffer, const UInt32 BufferSize) { Resource::DataStreamPtr NewStream( new Resource::MemoryStream(Buffer,BufferSize,true) ); this->DataStreams.push_back(NewStream); return NewStream; }
Resource::DataStreamPtr ResourceManager::CreateDataStream(const String& AssetName, void* Buffer, const UInt32 BufferSize) { Resource::DataStreamPtr NewStream( new Resource::MemoryStream(Buffer,BufferSize,true) ); this->NamedDataStreams.insert(std::pair<String,Resource::DataStreamPtr>(AssetName,NewStream)); return NewStream; }
/* *---------------------------------------------------------------------- * * NewReader -- * * Creates a stream to read streamType records for the given * request. The stream performs OS reads of up to bufflen bytes. * *---------------------------------------------------------------------- */ static FCGX_Stream *NewReader(FCGX_Request * reqDataPtr, int bufflen, int streamType) { return NewStream(reqDataPtr, bufflen, TRUE, streamType); }
/* *---------------------------------------------------------------------- * * NewWriter -- * * Creates a stream to write streamType FastCGI records, using * the ipcFd and RequestId contained in *reqDataPtr. * The stream performs OS writes of up to bufflen bytes. * *---------------------------------------------------------------------- */ static FCGX_Stream *NewWriter(FCGX_Request * reqDataPtr, int bufflen, int streamType) { return NewStream(reqDataPtr, bufflen, FALSE, streamType); }
static void HailExec(AgentConnection *conn, char *peer, char *recvbuffer, char *sendbuffer) { if (DEFINECLASSES[0] != '\0') { snprintf(sendbuffer, CF_BUFSIZE, "EXEC -D%s", DEFINECLASSES); } else { snprintf(sendbuffer, CF_BUFSIZE, "EXEC"); } if (SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Transmission rejected. (send: %s)", GetErrorStr()); DisconnectServer(conn); return; } /* TODO we are sending class data right after EXEC, when the server might * have already rejected us with BAD reply. So this class data with the * CFD_TERMINATOR will be interpreted by the server as a new, bogus * protocol command, and the server will complain. */ SendClassData(conn); FILE *fp = NewStream(peer); while (true) { memset(recvbuffer, 0, CF_BUFSIZE); int n_read = ReceiveTransaction(conn->conn_info, recvbuffer, NULL); if (n_read == -1) { break; } if (n_read == 0) /* connection closed */ { break; } if (strncmp(recvbuffer, CFD_TERMINATOR, strlen(CFD_TERMINATOR)) == 0) { break; } const size_t recv_len = strlen(recvbuffer); const char *ipaddr = conn->remoteip; if (strncmp(recvbuffer, "BAD:", 4) == 0) { fprintf(fp, "%s> !! %s\n", ipaddr, recvbuffer + 4); } /* cf-serverd >= 3.7 quotes command output with "> ". */ else if (strncmp(recvbuffer, "> ", 2) == 0) { fprintf(fp, "%s> -> %s", ipaddr, &recvbuffer[2]); } else { fprintf(fp, "%s> %s", ipaddr, recvbuffer); } if (recv_len > 0 && recvbuffer[recv_len - 1] != '\n') { /* We'll be printing double newlines here with new cf-serverd * versions, so check for already trailing newlines. */ /* TODO deprecate this path in a couple of versions. cf-serverd is * supposed to munch the newlines so we must always append one. */ fputc('\n', fp); } } if (fp != stdout) { fclose(fp); } DisconnectServer(conn); }
static void HailExec(AgentConnection *conn, char *peer) { char sendbuf[CF_BUFSIZE - CF_INBAND_OFFSET] = "EXEC"; size_t sendbuf_len = strlen(sendbuf); if (!NULL_OR_EMPTY(DEFINECLASSES)) { StrCat(sendbuf, sizeof(sendbuf), &sendbuf_len, " -D", 0); StrCat(sendbuf, sizeof(sendbuf), &sendbuf_len, DEFINECLASSES, 0); } if (!NULL_OR_EMPTY(REMOTEBUNDLES)) { StrCat(sendbuf, sizeof(sendbuf), &sendbuf_len, " -b ", 0); StrCat(sendbuf, sizeof(sendbuf), &sendbuf_len, REMOTEBUNDLES, 0); } if (sendbuf_len >= sizeof(sendbuf)) { Log(LOG_LEVEL_ERR, "Command longer than maximum transaction packet"); DisconnectServer(conn); return; } if (SendTransaction(conn->conn_info, sendbuf, 0, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Transmission rejected. (send: %s)", GetErrorStr()); DisconnectServer(conn); return; } /* TODO we are sending class data right after EXEC, when the server might * have already rejected us with BAD reply. So this class data with the * CFD_TERMINATOR will be interpreted by the server as a new, bogus * protocol command, and the server will complain. */ SendClassData(conn); char recvbuffer[CF_BUFSIZE]; FILE *fp = NewStream(peer); while (true) { memset(recvbuffer, 0, sizeof(recvbuffer)); if (ReceiveTransaction(conn->conn_info, recvbuffer, NULL) == -1) { break; } if (strncmp(recvbuffer, CFD_TERMINATOR, strlen(CFD_TERMINATOR)) == 0) { break; } const size_t recv_len = strlen(recvbuffer); const char *ipaddr = conn->remoteip; if (strncmp(recvbuffer, "BAD:", 4) == 0) { fprintf(fp, "%s> !! %s\n", ipaddr, recvbuffer + 4); } /* cf-serverd >= 3.7 quotes command output with "> ". */ else if (strncmp(recvbuffer, "> ", 2) == 0) { fprintf(fp, "%s> -> %s", ipaddr, &recvbuffer[2]); } else { fprintf(fp, "%s> %s", ipaddr, recvbuffer); } if (recv_len > 0 && recvbuffer[recv_len - 1] != '\n') { /* We'll be printing double newlines here with new cf-serverd * versions, so check for already trailing newlines. */ /* TODO deprecate this path in a couple of versions. cf-serverd is * supposed to munch the newlines so we must always append one. */ fputc('\n', fp); } } if (fp != stdout) { fclose(fp); } DisconnectServer(conn); }
HRESULT CWMPEventDispatch::Invoke( DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr ) { if (!pDispParams) return E_POINTER; if (pDispParams->cNamedArgs != 0) return DISP_E_NONAMEDARGS; HRESULT hr = DISP_E_MEMBERNOTFOUND; switch (dispIdMember) { case DISPID_WMPCOREEVENT_OPENSTATECHANGE: OpenStateChange(pDispParams->rgvarg[0].lVal /* NewState */ ); break; case DISPID_WMPCOREEVENT_PLAYSTATECHANGE: PlayStateChange(pDispParams->rgvarg[0].lVal /* NewState */); break; case DISPID_WMPCOREEVENT_AUDIOLANGUAGECHANGE: AudioLanguageChange(pDispParams->rgvarg[0].lVal /* LangID */); break; case DISPID_WMPCOREEVENT_STATUSCHANGE: StatusChange(); break; case DISPID_WMPCOREEVENT_SCRIPTCOMMAND: ScriptCommand(pDispParams->rgvarg[1].bstrVal /* scType */, pDispParams->rgvarg[0].bstrVal /* Param */ ); break; case DISPID_WMPCOREEVENT_NEWSTREAM: NewStream(); break; case DISPID_WMPCOREEVENT_DISCONNECT: Disconnect(pDispParams->rgvarg[0].lVal /* Result */ ); break; case DISPID_WMPCOREEVENT_BUFFERING: Buffering(pDispParams->rgvarg[0].boolVal /* Start */); break; case DISPID_WMPCOREEVENT_ERROR: Error(); break; case DISPID_WMPCOREEVENT_WARNING: Warning(pDispParams->rgvarg[1].lVal /* WarningType */, pDispParams->rgvarg[0].lVal /* Param */, pDispParams->rgvarg[2].bstrVal /* Description */); break; case DISPID_WMPCOREEVENT_ENDOFSTREAM: EndOfStream(pDispParams->rgvarg[0].lVal /* Result */ ); break; case DISPID_WMPCOREEVENT_POSITIONCHANGE: PositionChange(pDispParams->rgvarg[1].dblVal /* oldPosition */, pDispParams->rgvarg[0].dblVal /* newPosition */); break; case DISPID_WMPCOREEVENT_MARKERHIT: MarkerHit(pDispParams->rgvarg[0].lVal /* MarkerNum */); break; case DISPID_WMPCOREEVENT_DURATIONUNITCHANGE: DurationUnitChange(pDispParams->rgvarg[0].lVal /* NewDurationUnit */); break; case DISPID_WMPCOREEVENT_CDROMMEDIACHANGE: CdromMediaChange(pDispParams->rgvarg[0].lVal /* CdromNum */); break; case DISPID_WMPCOREEVENT_PLAYLISTCHANGE: PlaylistChange(pDispParams->rgvarg[1].pdispVal /* Playlist */, (WMPPlaylistChangeEventType) pDispParams->rgvarg[0].lVal /* change */); break; case DISPID_WMPCOREEVENT_CURRENTPLAYLISTCHANGE: CurrentPlaylistChange((WMPPlaylistChangeEventType) pDispParams->rgvarg[0].lVal /* change */); break; case DISPID_WMPCOREEVENT_CURRENTPLAYLISTITEMAVAILABLE: CurrentPlaylistItemAvailable(pDispParams->rgvarg[0].bstrVal /* bstrItemName */); break; case DISPID_WMPCOREEVENT_MEDIACHANGE: MediaChange(pDispParams->rgvarg[0].pdispVal /* Item */); break; case DISPID_WMPCOREEVENT_CURRENTMEDIAITEMAVAILABLE: CurrentMediaItemAvailable(pDispParams->rgvarg[0].bstrVal /* bstrItemName */); break; case DISPID_WMPCOREEVENT_CURRENTITEMCHANGE: CurrentItemChange(pDispParams->rgvarg[0].pdispVal /* pdispMedia */); break; case DISPID_WMPCOREEVENT_MEDIACOLLECTIONCHANGE: MediaCollectionChange(); break; case DISPID_WMPCOREEVENT_MEDIACOLLECTIONATTRIBUTESTRINGADDED: MediaCollectionAttributeStringAdded(pDispParams->rgvarg[1].bstrVal /* bstrAttribName */, pDispParams->rgvarg[0].bstrVal /* bstrAttribVal */ ); break; case DISPID_WMPCOREEVENT_MEDIACOLLECTIONATTRIBUTESTRINGREMOVED: MediaCollectionAttributeStringRemoved(pDispParams->rgvarg[1].bstrVal /* bstrAttribName */, pDispParams->rgvarg[0].bstrVal /* bstrAttribVal */ ); break; case DISPID_WMPCOREEVENT_MEDIACOLLECTIONATTRIBUTESTRINGCHANGED: MediaCollectionAttributeStringChanged(pDispParams->rgvarg[2].bstrVal /* bstrAttribName */, pDispParams->rgvarg[1].bstrVal /* bstrOldAttribVal */, pDispParams->rgvarg[0].bstrVal /* bstrNewAttribVal */); break; case DISPID_WMPCOREEVENT_PLAYLISTCOLLECTIONCHANGE: PlaylistCollectionChange(); break; case DISPID_WMPCOREEVENT_PLAYLISTCOLLECTIONPLAYLISTADDED: PlaylistCollectionPlaylistAdded(pDispParams->rgvarg[0].bstrVal /* bstrPlaylistName */ ); break; case DISPID_WMPCOREEVENT_PLAYLISTCOLLECTIONPLAYLISTREMOVED: PlaylistCollectionPlaylistRemoved(pDispParams->rgvarg[0].bstrVal /* bstrPlaylistName */ ); break; case DISPID_WMPCOREEVENT_PLAYLISTCOLLECTIONPLAYLISTSETASDELETED: PlaylistCollectionPlaylistSetAsDeleted(pDispParams->rgvarg[1].bstrVal /* bstrPlaylistName */, pDispParams->rgvarg[0].boolVal /* varfIsDeleted */); break; case DISPID_WMPCOREEVENT_MODECHANGE: ModeChange(pDispParams->rgvarg[1].bstrVal /* ModeName */, pDispParams->rgvarg[0].boolVal /* NewValue */); break; case DISPID_WMPCOREEVENT_MEDIAERROR: MediaError(pDispParams->rgvarg[0].pdispVal /* pMediaObject */); break; case DISPID_WMPCOREEVENT_OPENPLAYLISTSWITCH: OpenPlaylistSwitch(pDispParams->rgvarg[0].pdispVal /* pItem */); break; case DISPID_WMPCOREEVENT_DOMAINCHANGE: DomainChange(pDispParams->rgvarg[0].bstrVal /* strDomain */); break; case DISPID_WMPOCXEVENT_SWITCHEDTOPLAYERAPPLICATION: SwitchedToPlayerApplication(); break; case DISPID_WMPOCXEVENT_SWITCHEDTOCONTROL: SwitchedToControl(); break; case DISPID_WMPOCXEVENT_PLAYERDOCKEDSTATECHANGE: PlayerDockedStateChange(); break; case DISPID_WMPOCXEVENT_PLAYERRECONNECT: PlayerReconnect(); break; case DISPID_WMPOCXEVENT_CLICK: Click(pDispParams->rgvarg[3].iVal /* nButton */, pDispParams->rgvarg[2].iVal /* nShiftState */, pDispParams->rgvarg[1].lVal /* fX */, pDispParams->rgvarg[0].lVal /* fY */); break; case DISPID_WMPOCXEVENT_DOUBLECLICK: DoubleClick(pDispParams->rgvarg[3].iVal /* nButton */, pDispParams->rgvarg[2].iVal /* nShiftState */, pDispParams->rgvarg[1].lVal /* fX */, pDispParams->rgvarg[0].lVal /* fY */); break; case DISPID_WMPOCXEVENT_KEYDOWN: KeyDown(pDispParams->rgvarg[1].iVal /* nKeyCode */, pDispParams->rgvarg[0].iVal /* nShiftState */); break; case DISPID_WMPOCXEVENT_KEYPRESS: KeyPress(pDispParams->rgvarg[0].iVal /* nKeyAscii */); break; case DISPID_WMPOCXEVENT_KEYUP: KeyUp(pDispParams->rgvarg[1].iVal /* nKeyCode */, pDispParams->rgvarg[0].iVal /* nShiftState */); break; case DISPID_WMPOCXEVENT_MOUSEDOWN: MouseDown(pDispParams->rgvarg[3].iVal /* nButton */, pDispParams->rgvarg[2].iVal /* nShiftState */, pDispParams->rgvarg[1].lVal /* fX */, pDispParams->rgvarg[0].lVal /* fY */); break; case DISPID_WMPOCXEVENT_MOUSEMOVE: MouseMove(pDispParams->rgvarg[3].iVal /* nButton */, pDispParams->rgvarg[2].iVal /* nShiftState */, pDispParams->rgvarg[1].lVal /* fX */, pDispParams->rgvarg[0].lVal /* fY */); break; case DISPID_WMPOCXEVENT_MOUSEUP: MouseUp(pDispParams->rgvarg[3].iVal /* nButton */, pDispParams->rgvarg[2].iVal /* nShiftState */, pDispParams->rgvarg[1].lVal /* fX */, pDispParams->rgvarg[0].lVal /* fY */); break; } return( hr ); }
static void ParseStream(int type) { int ent; int tag; int flags; int skin; vec3_t source; vec3_t dest; stream_t *stream; float duration; model_t *models[4]; ent = MSG_ReadShort(); flags = MSG_ReadByte(); tag = flags&15; duration = (float)MSG_ReadByte()*0.05; skin = 0; if(type == TE_STREAM_COLORBEAM) { skin = MSG_ReadByte(); } source[0] = MSG_ReadCoord(); source[1] = MSG_ReadCoord(); source[2] = MSG_ReadCoord(); dest[0] = MSG_ReadCoord(); dest[1] = MSG_ReadCoord(); dest[2] = MSG_ReadCoord(); models[1] = models[2] = models[3] = NULL; switch(type) { case TE_STREAM_CHAIN: models[0] = Mod_ForName("models/stchain.mdl", true); break; case TE_STREAM_SUNSTAFF1: models[0] = Mod_ForName("models/stsunsf1.mdl", true); models[1] = Mod_ForName("models/stsunsf2.mdl", true); models[2] = Mod_ForName("models/stsunsf3.mdl", true); models[3] = Mod_ForName("models/stsunsf4.mdl", true); break; case TE_STREAM_SUNSTAFF2: models[0] = Mod_ForName("models/stsunsf5.mdl", true); models[2] = Mod_ForName("models/stsunsf3.mdl", true); models[3] = Mod_ForName("models/stsunsf4.mdl", true); break; case TE_STREAM_LIGHTNING: models[0] = Mod_ForName("models/stlghtng.mdl", true); // duration*=2; break; case TE_STREAM_LIGHTNING_SMALL: models[0] = Mod_ForName("models/stltng2.mdl", true); // duration*=2; break; case TE_STREAM_FAMINE: models[0] = Mod_ForName("models/fambeam.mdl", true); break; case TE_STREAM_COLORBEAM: models[0] = Mod_ForName("models/stclrbm.mdl", true); break; case TE_STREAM_ICECHUNKS: models[0] = Mod_ForName("models/stice.mdl", true); break; case TE_STREAM_GAZE: models[0] = Mod_ForName("models/stmedgaz.mdl", true); break; default: Sys_Error("ParseStream: bad type"); } if((stream = NewStream(ent, tag)) == NULL) { Con_Printf("stream list overflow\n"); return; } stream->type = type; stream->tag = tag; stream->flags = flags; stream->entity = ent; stream->skin = skin; stream->models[0] = models[0]; stream->models[1] = models[1]; stream->models[2] = models[2]; stream->models[3] = models[3]; stream->endTime = cl.time+duration; stream->lastTrailTime = 0; VectorCopy(source, stream->source); VectorCopy(dest, stream->dest); if(flags&STREAM_ATTACHED) { VectorSubtract(source, cl_entities[ent].origin, stream->offset); } }
void CPDF::Close() { Page *P; Font *F; // write Courier font Obj *CourierObj = NewObject(); fprintf(PDFFile, "%d 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Courier >>\nendobj\n", CourierObj->id); // write single dot XObject Obj *Dot = NewObject(); fprintf(PDFFile, "%d 0 obj\n<< /Type /XObject /Subtype /Form /FormType 1 /BBox [-0.5 -0.5 0.5 0.5] /Marix [1 0 0 1 0 0] /Resources << /ProcSet [/PDF] >> /Length 148 >>\nstream\n", Dot->id); fprintf(PDFFile, "0 0.5 m 0.27553 0.5 0.5 0.27553 0.5 0 c 0.5 -0.27553 0.27553 -0.5 0 -0.5 c -0.27553 -0.5 -0.5 -0.27553 -0.5 0 c -0.5 0.27553 -0.27553 0.5 0 0.5 c f\n"); fprintf(PDFFile, "endstream\nendobj\n"); // write custom fonts F = FontList; while(F) { int c; Obj *FontHead = NewObject(); F->id = FontHead->id; F->Glyphs[32].Begin(F->State); // 6/72 = 0.083333333333 fprintf(PDFFile, "%d 0 obj\n<< /Type /Font /Subtype /Type3 /FontBBox [0 0 %0.2f 10] /FontMatrix [0.083333333333 0 0 0.083333333333 0 0]", FontHead->id, (float)F->Glyphs[32].GetWidth() / (VIRTUAL_DPI / 72)); fprintf(PDFFile, " /CharProcs %d 0 R /Encoding %d 0 R /FirstChar 0 /LastChar 255 /Widths [", FontHead->id+2, FontHead->id+1); for(c = 0; c < 256; c++) { fprintf(PDFFile, "%0.2f ", (float)F->Glyphs[c].GetWidth() / (VIRTUAL_DPI / 72)); } fprintf(PDFFile, "] /ToUnicode %d 0 R >>\nendobj\n", FontHead->id+3); /* encoding */ Obj *T = NewObject(); fprintf(PDFFile, "%d 0 obj\n<< /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [0 ", FontHead->id+1); for(c = 0; c < 256; c++) { fprintf(PDFFile, "/%s_%d ", F->Name, c); } fprintf(PDFFile, "] >>\nendobj\n"); /* CharProcs */ T = NewObject(); fprintf(PDFFile, "%d 0 obj\n<< ", FontHead->id+2); for(c = 0; c < 256; c++) { fprintf(PDFFile, "/%s_%d %d 0 R ", F->Name, c, FontHead->id+4+c); } fprintf(PDFFile, ">>\nendobj\n"); /* ToUnicode (always the same) */ NewStream(); AddText("/CIDInit /ProcSet findresource begin\n"); AddText("12 dict begin\n"); AddText("begincmap\n"); AddText("/CIDSystemInfo\n"); AddText("<< /Registry (Adobe)\n"); AddText("/Ordering (UCS)\n"); AddText("/Supplement 0\n"); AddText(">> def\n"); AddText("/CMapName /Adobe-Identity-UCS def\n"); AddText("/CMapNameType 2 def\n"); AddText("1 begincodespacerange\n"); AddText("<00> <FF>\n"); AddText("endcodespacerange\n"); AddText("2 beginbfrange\n"); for(int base = 0; base < 0x100; base += 0x80) { Uint16 First32Targets[32] = { 0x00e0, 0x00e8, 0x00f9, 0x00f2, // à, è, ù, ò 0x00ec, 0x00ba, 0x00a3, 0x00a1, // ì, º, £, ¡ 0x00bf, 0x00d1, 0x00f1, 0x00a4, // ¿, Ñ, ñ, ¤ 0xfb05, 0x00c5, 0x00e5, 0x00e7, // ſt, Å, å, ç - ligature might be wrong 0x00a7, 0x00df, 0x00c6, 0x00e6, // §, ß, Æ, æ 0x00d8, 0x00f8, 0x00a8, 0x00c4, // Ø, ø, ¨, Ä 0x00d6, 0x00dc, 0x00e4, 0x00f6, // Ö, Ü, ä, ö 0x00df, 0x00c9, 0x00e9, 0xffe5 // ü, É, é, ¥ }; char Buffer[32]; /* table based mapping, for Latin supplement characters + the occasional oddity */ sprintf(Buffer, "<%02x> <%02x> [ ", base, base+0x1f); AddText(Buffer); for(int c = 0; c < 32; c++) { sprintf(Buffer, "<%04x> ", First32Targets[c]); AddText(Buffer); } AddText("]\n"); /* ASCII area */ sprintf(Buffer, "<%02x> <%02x> <0020>\n", base+0x20, base+0x7e); AddText(Buffer); /* zero with a slash (should have a combining long solidus overlay, can't seem to make that work) */ sprintf(Buffer, "<%02x> <%02x> <0030>\n", base+0x7f, base+0x7f); AddText(Buffer); } AddText("endbfrange\n"); AddText("endcmap\n"); AddText("CMapName currentdict /CMap defineresource pop\n"); AddText("end\n"); AddText("end\n"); EndStream(); /* actual glyphs */ for(c = 0; c < 256; c++) { Uint32 *M; F->Glyphs[c].Begin(); float x = 0; NewStream(); char TBuf[128]; sprintf(TBuf, "%0.2f 9 0 0 %0.2f 9 d1 ", (float)F->Glyphs[c].GetWidth() / (VIRTUAL_DPI / 72), (float)F->Glyphs[c].GetWidth() / (VIRTUAL_DPI / 72)); AddText(TBuf); while(M = F->Glyphs[c].GetLine()) { float y = 9; Uint32 RC = *M; while(RC&((GLYPHLINE_START << 1)-1)) { if(RC&GLYPHLINE_START) AddPoint( x, y); y -= 0.5f; RC <<= 1; } x += (float)F->Glyphs[c].GetXAdvance() / (VIRTUAL_DPI / 72); } EndStream(); } F = F->Next; } /* while(mask&((GLYPHLINE_START << 1)-1)) { if(mask&GLYPHLINE_START) PutDot(PosX, PosY); PosY += 5; mask <<= 1; } */ /* Obj *FontObj = NewObject(); fprintf(PDFFile, "%d 0 obj\n<< /Type /Font /Subtype /Type3 /FontBBox [0 0 750 750] /FontMatrix [0.001 0 0 0.001 0 0]", FontObj->id); fprintf(PDFFile, " /CharProcs %d 0 R /Encoding %d 0 R /FirstChar 97 /LastChar 98 /Widths [1000 1000] >>\nendobj\n", FontObj->id+2, FontObj->id+1); Obj *T = NewObject(); fprintf(PDFFile, "%d 0 obj\n<< /Type /Encoding /Differences [97 /square /triangle] >>\nendobj\n", FontObj->id+1); T = NewObject(); fprintf(PDFFile, "%d 0 obj\n<< /square %d 0 R /triangle %d 0 R >>\nendobj\n", FontObj->id+2, FontObj->id+3, FontObj->id+4); NewStream(); AddText("1000 0 0 0 750 750 d1 0 0 750 750 re f "); EndStream(); NewStream(); AddText("1000 0 0 0 750 750 d1 0 0 m 375 750 l 750 0 l f "); EndStream();*/ // fprintf(PDFFile, "%d 0 obj\n<< /square %d 0 R /triangle %d 0 R >>\nendobj\n", FontObj->id+2, FontObj->id+3, FontObj->id+4); // write actual pages P = PageList; int ObjectsIn = NumObjects; while(P) { P->FileOffset = ftell(PDFFile); P->id = NumObjects+1; NumObjects++; fprintf(PDFFile, "%d 0 obj\n\t", P->id); // page entry (just points to the outlines) fputs("<< /Type /Page\n\t\t", PDFFile); fprintf(PDFFile, "/Parent %d 0 R\n\t\t", ObjectsIn+NumPages+1); fprintf(PDFFile, "/MediaBox [0 0 %d %d]\n\t\t", P->Width, P->Height); fputs("/Contents ", PDFFile); Obj *O = *(P->FirstObj); if(P->Next) { while(O != *P->Next->FirstObj) { fprintf(PDFFile, "%d 0 R ", O->id); O = O->Next; } } else { while(O != CourierObj) { fprintf(PDFFile, "%d 0 R ", O->id); O = O->Next; } } fputs(">>\nendobj\n", PDFFile); P = P->Next; } // write pages entry long PagesPos = ftell(PDFFile); fprintf(PDFFile, "%d 0 obj\n\t", NumObjects+1); NumObjects++; // pages entry (there is one) fputs("<< /Type /Pages\n\t\t", PDFFile); fprintf(PDFFile, "/Resources << /XObject << /Dot %d 0 R >> /Font << /Courier %d 0 R ", Dot->id, CourierObj->id); F = FontList; while(F) { fprintf(PDFFile, "/%s %d 0 R ", F->Name, F->id); F = F->Next; } fprintf(PDFFile, " >> >>\n\t\t"); fputs("/Kids [", PDFFile); P = PageList; while(P) { fprintf(PDFFile, "%d 0 R ", P->id); P = P->Next; } fputs("]\n\t\t", PDFFile); fprintf(PDFFile, "/Count %d\n\t", NumPages); fputs(">>\nendobj\n", PDFFile); // write catalogue long CataloguePos = ftell(PDFFile); fprintf(PDFFile, "%d 0 obj\n\t", NumObjects+1); NumObjects++; fprintf(PDFFile, "<< /Type /Catalog /Pages %d 0 R >>\nendobj\n", NumObjects-1); // write xref table long xrefpos = ftell(PDFFile); fprintf(PDFFile, "xref\n0 %d\n", NumObjects+1); fprintf(PDFFile, "0000000000 65535 f \n"); Obj *O = ObjList; while(O) { fprintf(PDFFile, "%010d 00000 n \n", (int)O->FileOffset); O = O->Next; } P = PageList; while(P) { fprintf(PDFFile, "%010d 00000 n \n", (int)P->FileOffset); P = P->Next; } fprintf(PDFFile, "%010d 00000 n \n", (int)PagesPos); fprintf(PDFFile, "%010d 00000 n \n", (int)CataloguePos); fprintf(PDFFile, "trailer\n\t<</Size %d\n\t\t/Root %d 0 R\n\t>>\n", NumObjects+1, NumObjects); fprintf(PDFFile, "startxref\n%d\n", (int)xrefpos); fputs("%%EOF", PDFFile); fclose(PDFFile); // free memory while(PageList) { Page *N = PageList->Next; delete PageList; PageList = N; } while(ObjList) { Obj *N = ObjList->Next; delete ObjList; ObjList = N; } while(FontList) { Font *N = FontList->Next; delete FontList; FontList = N; } }