| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- {
- $Project$
- $Workfile$
- $Revision$
- $DateUTC$
- $Id$
- This file is part of the Indy (Internet Direct) project, and is offered
- under the dual-licensing agreement described on the Indy website.
- (http://www.indyproject.org/)
- Copyright:
- (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
- }
- {
- $Log$
- }
- {
- Rev 1.12 7/24/04 12:56:14 PM RLebeau
- Compiler fix for Print(TIdBytes)
- Rev 1.11 7/23/04 7:15:16 PM RLebeau
- Added extra exception handling to various Print...() methods
- Rev 1.10 2004.05.20 11:36:50 AM czhower
- IdStreamVCL
- Rev 1.9 2004.03.03 11:54:32 AM czhower
- IdStream change
- Rev 1.8 2004.02.03 5:43:56 PM czhower
- Name changes
- Rev 1.7 1/21/2004 3:11:22 PM JPMugaas
- InitComponent
- Rev 1.6 10/24/2003 02:54:52 PM JPMugaas
- These should now work with the new code.
- Rev 1.5 2003.10.24 10:43:10 AM czhower
- TIdSTream to dos
- Rev 1.4 2003.10.12 4:04:00 PM czhower
- compile todos
- Rev 1.3 2/24/2003 09:07:26 PM JPMugaas
- Rev 1.2 2/6/2003 03:18:08 AM JPMugaas
- Updated components that compile with Indy 10.
- Rev 1.1 12/6/2002 05:30:18 PM JPMugaas
- Now decend from TIdTCPClientCustom instead of TIdTCPClient.
- Rev 1.0 11/13/2002 07:56:22 AM JPMugaas
- 27.07. rewrite component for integration
- in Indy core library
- }
- unit IdLPR;
- {
- Indy Line Print Remote TIdLPR
- Version 9.1.0
- Original author Mario Mueller
- home: www.hemasoft.de
- mail: [email protected]
- }
- interface
- {$i IdCompilerDefines.inc}
- uses
- Classes,
- IdAssignedNumbers, IdGlobal, IdException, IdTCPClient,
- IdComponent;
- type
- TIdLPRFileFormat =
- (ffCIF, // CalTech Intermediate Form
- ffDVI, // DVI (TeX output).
- ffFormattedText, //add formatting as needed to text file
- ffPlot, // Berkeley Unix plot library
- ffControlCharText, //text file with control charactors
- ffDitroff, // ditroff output
- ffPostScript, //Postscript output file
- ffPR,//'pr' format {Do not Localize}
- ffFORTRAM, // FORTRAN carriage control
- ffTroff, //Troff output
- ffSunRaster); // Sun raster format file
- const
- DEF_FILEFORMAT = ffControlCharText;
- DEF_INDENTCOUNT = 0;
- DEF_BANNERPAGE = False;
- DEF_OUTPUTWIDTH = 0;
- DEF_MAILWHENPRINTED = False;
- type
- TIdLPRControlFile = class(TPersistent)
- protected
- FBannerClass: String; // 'C' {Do not Localize}
- FHostName: String; // 'H' {Do not Localize}
- FIndentCount: Integer; // 'I' {Do not Localize}
- FJobName: String; // 'J' {Do not Localize}
- FBannerPage: Boolean; // 'L' {Do not Localize}
- FUserName: String; // 'P' {Do not Localize}
- FOutputWidth: Integer; // 'W' {Do not Localize}
- FFileFormat : TIdLPRFileFormat;
- FTroffRomanFont : String; //substitue the Roman font with the font in file
- FTroffItalicFont : String;//substitue the Italic font with the font in file
- FTroffBoldFont : String; //substitue the bold font with the font in file
- FTroffSpecialFont : String; //substitue the special font with the font
- //in this file
- FMailWhenPrinted : Boolean; //mail me when you have printed the job
- public
- constructor Create;
- procedure Assign(Source: TPersistent); override;
- property HostName: String read FHostName write FHostName;
- published
- property BannerClass: String read FBannerClass write FBannerClass;
- property IndentCount: Integer read FIndentCount write FIndentCount default DEF_INDENTCOUNT;
- property JobName: String read FJobName write FJobName;
- property BannerPage: Boolean read FBannerPage write FBannerPage default DEF_BANNERPAGE;
- property UserName: String read FUserName write FUserName;
- property OutputWidth: Integer read FOutputWidth write FOutputWidth default DEF_OUTPUTWIDTH;
- property FileFormat: TIdLPRFileFormat read FFileFormat write FFileFormat default DEF_FILEFORMAT;
- {font data }
- property TroffRomanFont : String read FTroffRomanFont write FTroffRomanFont;
- property TroffItalicFont : String read FTroffItalicFont write FTroffItalicFont;
- property TroffBoldFont : String read FTroffBoldFont write FTroffBoldFont;
- property TroffSpecialFont : String read FTroffSpecialFont write FTroffSpecialFont;
- {misc}
- property MailWhenPrinted : Boolean read FMailWhenPrinted write FMailWhenPrinted default DEF_MAILWHENPRINTED;
- end;
- type
- TIdLPRStatus = (psPrinting, psJobCompleted, psError, psGettingQueueState,
- psGotQueueState, psDeletingJobs, psJobsDeleted, psPrintingWaitingJobs,
- psPrintedWaitingJobs);
- type
- TIdLPRStatusEvent = procedure(ASender: TObject;
- const AStatus: TIdLPRStatus;
- const AStatusText: String) of object;
- type
- TIdLPR = class(TIdTCPClientCustom)
- protected
- FOnLPRStatus: TIdLPRStatusEvent;
- FQueue: String;
- FJobId: Integer;
- FControlFile: TIdLPRControlFile;
- procedure DoOnLPRStatus(const AStatus: TIdLPRStatus;
- const AStatusText: String);
- procedure SeTIdLPRControlFile(const Value: TIdLPRControlFile);
- procedure CheckReply;
- function GetJobId: String;
- procedure SetJobId(const Value: String);
- procedure InternalPrint(Data: TStream);
- function GetControlData: String;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Connect; override;
- procedure Print(const AText: String); overload;
- procedure Print(const ABuffer: TIdBytes); overload;
- procedure PrintFile(const AFileName: String);
- function GetQueueState(const AShortFormat: Boolean = False; const AList : String = '') : String; {Do not Localize}
- procedure PrintWaitingJobs;
- procedure RemoveJobList(const AList: String; const AAsRoot: Boolean = False);
- property JobId: String read GetJobId write SetJobId;
- published
- property Queue: String read FQueue write FQueue;
- property ControlFile: TIdLPRControlFile read FControlFile write SeTIdLPRControlFile;
- property Host;
- property Port default IdPORT_LPD;
- property OnLPRStatus: TIdLPRStatusEvent read FOnLPRStatus write FOnLPRStatus;
- end;
- type
- EIdLPRErrorException = class(EIdException);
- implementation
- uses
- IdGlobalProtocols, IdResourceStringsProtocols, IdStack, IdStackConsts,
- SysUtils;
- { TIdLPR }
- constructor TIdLPR.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- Port := IdPORT_LPD;
- Queue := 'pr1'; {Do not Localize}
- FJobId := 1;
- FControlFile := TIdLPRControlFile.Create;
- // Restriction in RFC 1179
- // The source port must be in the range 721 to 731, inclusive.
- BoundPortMin := 721;
- BoundPortMax := 731;
- end;
- destructor TIdLPR.Destroy;
- begin
- FControlFile.Free;
- inherited Destroy;
- end;
- procedure TIdLPR.Connect;
- var
- LPort: TIdPort;
- begin
- // RLebeau 3/7/2010: there is a problem on Windows where sometimes it will
- // not raise a WSAEADDRINUSE error in TIdSocketHandle.TryBind(), but will
- // delay it until TIdSocketHandle.Connect() instead. So we will loop here
- // to force a Connect() on each port, rather than let TIdSocketHandle do
- // the looping in BindPortReserved(). If this logic proves useful in other
- // protocols, we can move it into TIdSocketHandle later on...
- // AWinkelsdorf 3/9/2010: Implemented, adjusted to use BoundPortMax and
- // BoundPortMin
- // looping backwards because that is what TIdSocketHandle.BindPortReserved() does
- for LPort := BoundPortMax downto BoundPortMin do
- begin
- BoundPort := LPort;
- try
- inherited Connect;
- Exit;
- except
- on E: EIdCouldNotBindSocket do begin end;
- on E: EIdSocketError do begin
- if E.LastError <> Id_WSAEADDRINUSE then begin
- raise;
- end;
- // Socket already in use, cleanup and try again with the next
- Disconnect;
- end;
- end;
- end;
- // no local ports could be bound successfully
- raise EIdCanNotBindPortInRange.CreateFmt(RSLPRCannotBindRange, [BoundPortMin, BoundPortMax]);
- end;
- procedure TIdLPR.Print(const AText: String);
- var
- LStream: TStream;
- begin
- LStream := TMemoryStream.Create;
- try
- WriteStringToStream(LStream, AText, IndyTextEncoding_8Bit);
- LStream.Position := 0;
- InternalPrint(LStream);
- finally
- LStream.Free;
- end;
- end;
- procedure TIdLPR.Print(const ABuffer: TIdBytes);
- var
- LStream: TStream;
- begin
- LStream := TIdReadOnlyMemoryBufferStream.Create(PByte(ABuffer), Length(ABuffer));
- try
- InternalPrint(LStream);
- finally
- LStream.Free;
- end;
- end;
- procedure TIdLPR.PrintFile(const AFileName: String);
- var
- LStream: TIdReadFileExclusiveStream;
- p: Integer;
- begin
- p := RPos(GPathDelim, AFileName);
- ControlFile.JobName := Copy(AFileName, p+1, Length(AFileName)-p);
- LStream := TIdReadFileExclusiveStream.Create(AFileName);
- try
- InternalPrint(LStream);
- finally
- LStream.Free;
- end;
- end;
- function TIdLPR.GetJobId: String;
- begin
- Result := IndyFormat('%.3d', [FJobId]); {Do not Localize}
- end;
- procedure TIdLPR.SetJobId(const Value: String);
- var
- I: Integer;
- begin
- I := IndyStrToInt(Value);
- if I < 999 then begin
- FJobId := I;
- end;
- end;
- procedure TIdLPR.InternalPrint(Data: TStream);
- begin
- try
- if not Connected then begin
- Exit;
- end;
- Inc(FJobID);
- if FJobID > 999 then begin
- FJobID := 1;
- end;
- DoOnLPRStatus(psPrinting, JobID);
- try
- ControlFile.HostName := GStack.HostName
- except
- ControlFile.HostName := 'localhost'; {Do not Localize}
- end;
- // Receive a printer job
- IOHandler.Write(#02 + Queue + LF);
- CheckReply;
- // Receive control file
- IOHandler.Write(#02 + IntToStr(Length(GetControlData)) + ' cfA' + JobId + ControlFile.HostName + LF); {Do not Localize}
- CheckReply;
- // Send control file
- IOHandler.Write(GetControlData);
- IOHandler.Write(#0);
- CheckReply;
- // Send data file
- IOHandler.Write(#03 + IntToStr(Data.Size) + ' dfA' + JobId + ControlFile.HostName + LF); {Do not Localize}
- CheckReply;
- // Send data
- IOHandler.Write(Data);
- IOHandler.Write(#0);
- CheckReply;
- DoOnLPRStatus(psJobCompleted, JobID);
- except
- on E: Exception do begin
- DoOnLPRStatus(psError, E.Message);
- end;
- end;
- end;
- function TIdLPR.GetQueueState(const AShortFormat: Boolean = False; const AList : String = '') : String; {Do not Localize}
- begin
- DoOnLPRStatus(psGettingQueueState, AList);
- if AShortFormat then begin
- IOHandler.Write(#03 + Queue + ' ' + AList + LF) {Do not Localize}
- end else begin
- IOHandler.Write(#04 + Queue + ' ' + AList + LF); {Do not Localize}
- end;
- // This was the original code - problematic as this is more than one line
- // read until I close the connection
- // result:=ReadLn(LF);
- Result := IOHandler.AllData;
- DoOnLPRStatus(psGotQueueState, result);
- end;
- function TIdLPR.GetControlData: String;
- var
- Data: String;
- begin
- Data := ''; {Do not Localize}
- try
- // H - Host name
- Data := Data + 'H' + FControlFile.HostName + LF; {Do not Localize}
- // P - User identification
- Data := Data + 'P' + FControlFile.UserName + LF; {Do not Localize}
- // J - Job name for banner page
- if FControlFile.JobName <> '' then begin
- Data := Data + 'J' + FControlFile.JobName + LF; {Do not Localize}
- end else begin
- Data := Data + 'JcfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- //mail when printed
- if FControlFile.FMailWhenPrinted then begin
- Data := Data + 'M' + FControlFile.UserName + LF; {Do not Localize}
- end;
- case FControlFile.FFileFormat of
- ffCIF : // CalTech Intermediate Form
- begin
- Data := Data + 'cdfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffDVI : // DVI (TeX output).
- begin
- Data := Data + 'ddfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffFormattedText : //add formatting as needed to text file
- begin
- Data := Data + 'fdfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffPlot : // Berkeley Unix plot library
- begin
- Data := Data + 'gdfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffControlCharText : //text file with control charactors
- begin
- Data := Data + 'ldfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffDitroff : // ditroff output
- begin
- Data := Data + 'ndfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffPostScript : //Postscript output file
- begin
- Data := Data + 'odfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffPR : //'pr' format {Do not Localize}
- begin
- Data := Data + 'pdfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffFORTRAM : // FORTRAN carriage control
- begin
- Data := Data + 'rdfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffTroff : //Troff output
- begin
- Data := Data + 'ldfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- end;
- ffSunRaster : // Sun raster format file
- begin
- end;
- end;
- // U - Unlink data file
- Data := Data + 'UdfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- // N - Name of source file
- Data := Data + 'NcfA' + JobId + FControlFile.HostName + LF; {Do not Localize}
- if FControlFile.FFileFormat = ffFormattedText then begin
- if FControlFile.IndentCount > 0 then begin
- Data := Data + 'I' + IntToStr(FControlFile.IndentCount) + LF; {Do not Localize}
- end;
- if FControlFile.OutputWidth > 0 then begin
- Data := Data + 'W' + IntToStr(FControlFile.OutputWidth) + LF; {Do not Localize}
- end;
- end;
- if FControlFile.BannerClass <> '' then begin
- Data := Data + 'C' + FControlFile.BannerClass + LF; {Do not Localize}
- end;
- if FControlFile.BannerPage then begin
- Data := Data + 'L' + FControlFile.UserName + LF; {Do not Localize}
- end;
- if FControlFile.TroffRomanFont <> '' then begin
- Data := Data + '1' + FControlFile.TroffRomanFont + LF; {Do not Localize}
- end;
- if FControlFile.TroffItalicFont <> '' then begin
- Data := Data + '2' + FControlFile.TroffItalicFont + LF; {Do not Localize}
- end;
- if FControlFile.TroffBoldFont <> '' then begin
- Data := Data + '3' + FControlFile.TroffBoldFont + LF; {Do not Localize}
- end;
- if FControlFile.TroffSpecialFont <> '' then begin
- Data := Data + '4' + FControlFile.TroffSpecialFont + LF; {Do not Localize}
- end;
- Result := Data;
- except
- Result := 'error'; {Do not Localize}
- end;
- end;
- procedure TIdLPR.SeTIdLPRControlFile(const Value: TIdLPRControlFile);
- begin
- FControlFile.Assign(Value);
- end;
- procedure TIdLPR.PrintWaitingJobs;
- begin
- try
- DoOnLPRStatus(psPrintingWaitingJobs, ''); {Do not Localize}
- IOHandler.Write(#03 + Queue + LF);
- CheckReply;
- DoOnLPRStatus(psPrintedWaitingJobs, ''); {Do not Localize}
- except
- on E: Exception do begin
- DoOnLPRStatus(psError, E.Message);
- end;
- end;
- end;
- procedure TIdLPR.RemoveJobList(const AList: String; const AAsRoot: Boolean = False);
- begin
- try
- DoOnLPRStatus(psDeletingJobs, JobID);
- if AAsRoot then begin
- {Only root can delete other people's print jobs} {Do not Localize}
- IOHandler.Write(#05 + Queue + ' root ' + AList + LF); {Do not Localize}
- end else begin
- IOHandler.Write(#05 + Queue + ' ' + ControlFile.UserName + ' ' + AList + LF); {Do not Localize}
- end;
- CheckReply;
- DoOnLPRStatus(psJobsDeleted, JobID);
- except
- on E: Exception do begin
- DoOnLPRStatus(psError, E.Message);
- end;
- end;
- end;
- procedure TIdLPR.CheckReply;
- var
- Ret : Byte;
- begin
- Ret := IOHandler.ReadByte;
- if Ret <> $00 then begin
- raise EIdLPRErrorException.CreateFmt(RSLPRError, [Integer(Ret), JobID]);
- end;
- end;
- procedure TIdLPR.DoOnLPRStatus(const AStatus: TIdLPRStatus; const AStatusText: String);
- begin
- if Assigned(FOnLPRStatus) then begin
- FOnLPRStatus(Self, AStatus, AStatusText);
- end;
- end;
- { TIdLPRControlFile }
- procedure TIdLPRControlFile.Assign(Source: TPersistent);
- var
- cnt : TIdLPRControlFile;
- begin
- if Source is TIdLPRControlFile then
- begin
- cnt := Source as TIdLPRControlFile;
- FBannerClass := cnt.BannerClass;
- FIndentCount := cnt.IndentCount;
- FJobName := cnt.JobName;
- FBannerPage := cnt.BannerPage;
- FUserName := cnt.UserName;
- FOutputWidth := cnt.OutputWidth;
- FFileFormat := cnt.FileFormat;
- FTroffRomanFont := cnt.TroffRomanFont;
- FTroffItalicFont := cnt.TroffItalicFont;
- FTroffBoldFont := cnt.TroffBoldFont;
- FTroffSpecialFont := cnt.TroffSpecialFont;
- FMailWhenPrinted := cnt.MailWhenPrinted;
- end else begin
- inherited Assign(Source);
- end;
- end;
- constructor TIdLPRControlFile.Create;
- begin
- inherited Create;
- try
- HostName := GStack.HostName;
- except
- HostName := RSLPRUnknown;
- end;
- FFileFormat := DEF_FILEFORMAT;
- FIndentCount := DEF_INDENTCOUNT;
- FBannerPage := DEF_BANNERPAGE;
- FOutputWidth := DEF_OUTPUTWIDTH;
- end;
- end.
|