PPD parser and configuration UI prototype from 2004. Maybe it can be of some use for the CUPS port HCD 2008 project.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26007 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
SubDir HAIKU_TOP src tests add-ons print ;
|
||||
|
||||
# Skip PCL6 as jetlib.h is not in repository any more
|
||||
# TODO if there are no license issues add it to directory "pcl6"
|
||||
#SubInclude HAIKU_TOP src tests add-ons print pcl6 ;
|
||||
SubInclude HAIKU_TOP src tests add-ons print pdf ;
|
||||
SubInclude HAIKU_TOP src tests add-ons print pcl6 ;
|
||||
SubInclude HAIKU_TOP src tests add-ons print ppd ;
|
||||
SubInclude HAIKU_TOP src tests add-ons print transports ;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
SubDir HAIKU_TOP src tests add-ons print ppd ;
|
||||
|
||||
SubInclude HAIKU_TOP src tests add-ons print ppd model ;
|
||||
SubInclude HAIKU_TOP src tests add-ons print ppd parser ;
|
||||
SubInclude HAIKU_TOP src tests add-ons print ppd ui ;
|
||||
SubInclude HAIKU_TOP src tests add-ons print ppd test ;
|
||||
@@ -0,0 +1,78 @@
|
||||
PPD
|
||||
|
||||
# translationKeyword only if stand-alone = no *Keyword statements
|
||||
"*Default"Keyword ":" StringValue ["/" translationString ].
|
||||
"*"Keyword [Option ["/" translationString ]] ":" Value ["/" translationString ].
|
||||
"*?"Keyword ":" InvocationValue ["/" translationString ].
|
||||
"*Param"Keyword [Option ["/" translationString ]] ":" Value ["/" translationString ].
|
||||
|
||||
Line comments start with "*%".
|
||||
|
||||
*Include
|
||||
|
||||
Keyword = ident. # ,'.',/
|
||||
Option = ident {"." ident}.
|
||||
# translationString must not follow SymbolValue!
|
||||
# translationString is terminated by ":" if it follows a Option
|
||||
# or CR if it follows a Value.
|
||||
Value = InvocationValue | QuotedValue | SymbolValue | StringValue | NoValue.
|
||||
|
||||
# ps code
|
||||
# requires statement with option keyword!
|
||||
# Must end with in separate line *End if multiline.
|
||||
InvocationValue = '"' printable '"' ["/" translationString ].
|
||||
|
||||
# requires statement without an option keyword!
|
||||
# *JCL can have an option keyword!
|
||||
# Must end with in separate line *End if multiline.
|
||||
QuotedValue = '"' literalSubstring '"'.
|
||||
|
||||
SymbolValue = "^" printable. # without whitespaces
|
||||
|
||||
# In case of translation string it is separated by newline or slash.
|
||||
StringValue = printable . # first char must not be " or ^
|
||||
|
||||
literalSubstring = { hexadecimalSubstring | char }.
|
||||
|
||||
hexadecimalSubstring = "<" { whitespace* hexdigit hexdigit} ">".
|
||||
hexdigit = ['0'..'9','a'..'f','A'..'F'].
|
||||
|
||||
# No option keyword present. Keyword stands alone.
|
||||
NoValue =.
|
||||
|
||||
ident = identChar+.
|
||||
identChar = [33..126].
|
||||
|
||||
printable = printableChar+.
|
||||
printableChar = [32..126] | tab | lf | cr. # " belongs not to printableChar!
|
||||
|
||||
translationString = literalSubstring. # without lf and cr.
|
||||
|
||||
char = [32..255] | tab | lf | cr.
|
||||
|
||||
whitespace= space | tab.
|
||||
|
||||
tab=9.
|
||||
lf=10.
|
||||
cr=13.
|
||||
space=32.
|
||||
|
||||
max size of MainKeyword = 40 characters
|
||||
|
||||
File Structure see 3.8
|
||||
|
||||
Standard Option Values:
|
||||
True | False | None | Unknown
|
||||
|
||||
|
||||
OpenUI Keyword: PickOne | PickMany | Boolean
|
||||
CloseUI: Keyword
|
||||
Open[Sub]Group: string
|
||||
# InstallableOptions is a registered option!
|
||||
Close[Sub]Group: string
|
||||
|
||||
UIConstraints: keyword1 option1 keyword2 option2
|
||||
# option 1 can be omitted see page 57
|
||||
|
||||
# Unique name
|
||||
ModelName: "text"
|
||||
@@ -0,0 +1,17 @@
|
||||
Scanner/Parser:
|
||||
Handle JCLKeywords correctly.
|
||||
Convert strings according to LanguageEncoding.
|
||||
|
||||
PPDConfigView.cpp:
|
||||
Add outline sub items in reverse order
|
||||
Provide UI for single and multiple choice
|
||||
Read settings
|
||||
Write settings
|
||||
Read default settings
|
||||
Revert and OK button
|
||||
Handle constraints
|
||||
|
||||
Integrate to PS driver
|
||||
- Page setup dialog
|
||||
- Job setup dialog
|
||||
- Provide PS driver setup model selection dialog
|
||||
@@ -0,0 +1,12 @@
|
||||
SubDir HAIKU_TOP src tests add-ons print ppd model ;
|
||||
|
||||
# SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
StaticLibrary libppdtest.a :
|
||||
PPD.cpp
|
||||
Statement.cpp
|
||||
StatementList.cpp
|
||||
StatementListVisitor.cpp
|
||||
StatementWrapper.cpp
|
||||
Value.cpp
|
||||
;
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "PPD.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
PPD::PPD()
|
||||
: StatementList(true)
|
||||
, fSymbols(false)
|
||||
{
|
||||
}
|
||||
|
||||
PPD::~PPD()
|
||||
{
|
||||
}
|
||||
|
||||
void PPD::Print()
|
||||
{
|
||||
printf("<ppd>\n");
|
||||
StatementList::Print();
|
||||
printf("</ppd>\n");
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _PPD_H
|
||||
#define _PPD_H
|
||||
|
||||
#include "Statement.h"
|
||||
|
||||
// PostScript Printer Definiton
|
||||
class PPD : public StatementList {
|
||||
private:
|
||||
StatementList fSymbols;
|
||||
|
||||
public:
|
||||
PPD();
|
||||
virtual ~PPD();
|
||||
|
||||
// Prints the PPD to stdout in XML
|
||||
void Print();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "Statement.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
Statement::Statement()
|
||||
: fType(kUnknown)
|
||||
, fKeyword(NULL)
|
||||
, fOption(NULL)
|
||||
, fValue(NULL)
|
||||
, fChildren(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Statement::~Statement()
|
||||
{
|
||||
delete fKeyword;
|
||||
delete fOption;
|
||||
delete fValue;
|
||||
delete fChildren;
|
||||
}
|
||||
|
||||
void Statement::SetType(Type type)
|
||||
{
|
||||
fType = type;
|
||||
}
|
||||
|
||||
Statement::Type Statement::GetType()
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
void Statement::SetKeyword(BString* keyword)
|
||||
{
|
||||
fKeyword = keyword;
|
||||
}
|
||||
|
||||
BString* Statement::GetKeyword()
|
||||
{
|
||||
return fKeyword;
|
||||
}
|
||||
|
||||
void Statement::SetOption(Value* option)
|
||||
{
|
||||
fOption = option;
|
||||
}
|
||||
|
||||
Value* Statement::GetOption()
|
||||
{
|
||||
return fOption;
|
||||
}
|
||||
|
||||
|
||||
void Statement::SetValue(Value* value)
|
||||
{
|
||||
fValue = value;
|
||||
}
|
||||
|
||||
Value* Statement::GetValue()
|
||||
{
|
||||
return fValue;
|
||||
}
|
||||
|
||||
StatementList* Statement::GetChildren()
|
||||
{
|
||||
return fChildren;
|
||||
}
|
||||
|
||||
void Statement::AddChild(Statement* statement)
|
||||
{
|
||||
if (fChildren == NULL) {
|
||||
fChildren = new StatementList(true);
|
||||
}
|
||||
fChildren->Add(statement);
|
||||
}
|
||||
|
||||
const char* Statement::GetKeywordString()
|
||||
{
|
||||
if (fKeyword != NULL) {
|
||||
return fKeyword->String();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* Statement::GetOptionString()
|
||||
{
|
||||
Value* option = GetOption();
|
||||
if (option != NULL) {
|
||||
return option->GetValueString();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* Statement::GetTranslationString()
|
||||
{
|
||||
Value* option = GetOption();
|
||||
if (option != NULL) {
|
||||
return option->GetTranslationString();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* Statement::GetValueString()
|
||||
{
|
||||
Value* value = GetValue();
|
||||
if (value != NULL) {
|
||||
return value->GetValueString();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* Statement::GetValueTranslationString()
|
||||
{
|
||||
Value* value = GetValue();
|
||||
if (value != NULL) {
|
||||
return value->GetTranslationString();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char* Statement::ElementForType() {
|
||||
switch (fType) {
|
||||
case kDefault: return "Default";
|
||||
break;
|
||||
case kParam: return "Param";
|
||||
break;
|
||||
case kQuery: return "Query";
|
||||
break;
|
||||
case kValue: return "Value";
|
||||
break;
|
||||
case kUnknown: return "Unknown";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Statement::Print()
|
||||
{
|
||||
bool hasValue = fValue != NULL;
|
||||
bool hasOption = fOption != NULL;
|
||||
|
||||
printf("<%s", ElementForType());
|
||||
|
||||
if (fKeyword != NULL) {
|
||||
printf(" keyword=\"%s\"", fKeyword->String());
|
||||
}
|
||||
|
||||
if (hasValue || hasOption) {
|
||||
printf(">\n");
|
||||
} else {
|
||||
printf("/>\n");
|
||||
}
|
||||
|
||||
|
||||
if (hasOption) {
|
||||
printf("\t<option>\n");
|
||||
fOption->Print();
|
||||
printf("\t</option>\n");
|
||||
}
|
||||
|
||||
|
||||
if (hasValue) {
|
||||
printf("\t<value>\n");
|
||||
fValue->Print();
|
||||
printf("\t</value>\n");
|
||||
}
|
||||
|
||||
if (GetChildren() != NULL) {
|
||||
printf("\t<children>\n");
|
||||
GetChildren()->Print();
|
||||
printf("\t</children>\n");
|
||||
}
|
||||
|
||||
if (hasValue || hasOption) {
|
||||
printf("</%s>\n\n", ElementForType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _STATEMENT_H
|
||||
#define _STATEMENT_H
|
||||
|
||||
#include "StatementList.h"
|
||||
#include "Value.h"
|
||||
|
||||
class Statement
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
kDefault,
|
||||
kQuery,
|
||||
kValue,
|
||||
kParam,
|
||||
kUnknown
|
||||
};
|
||||
|
||||
private:
|
||||
Type fType;
|
||||
BString* fKeyword;
|
||||
Value* fOption;
|
||||
Value* fValue;
|
||||
StatementList* fChildren;
|
||||
|
||||
const char* ElementForType();
|
||||
|
||||
public:
|
||||
Statement();
|
||||
virtual ~Statement();
|
||||
|
||||
void SetType(Type type);
|
||||
Type GetType();
|
||||
|
||||
void SetKeyword(BString* keyword);
|
||||
// mandatory in a valid statement
|
||||
BString* GetKeyword();
|
||||
|
||||
void SetOption(Value* value);
|
||||
// optional in a valid statement
|
||||
Value* GetOption();
|
||||
|
||||
void SetValue(Value* value);
|
||||
// optional in a valid statement
|
||||
Value* GetValue();
|
||||
|
||||
void AddChild(Statement* statement);
|
||||
// optional in a valid statement
|
||||
StatementList* GetChildren();
|
||||
|
||||
// convenience methods
|
||||
bool IsDefaultStatement() { return fType == kDefault; }
|
||||
bool IsQueryStatement() { return fType == kQuery; }
|
||||
bool IsValueStatement() { return fType == kValue; }
|
||||
bool IsParamStatement() { return fType == kParam; }
|
||||
bool IsUnknownStatement() { return fType == kUnknown; }
|
||||
|
||||
const char* GetKeywordString();
|
||||
const char* GetOptionString();
|
||||
const char* GetTranslationString();
|
||||
const char* GetValueString();
|
||||
const char* GetValueTranslationString();
|
||||
|
||||
void Print();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "StatementList.h"
|
||||
#include "Statement.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
StatementList::StatementList(bool ownsStatements)
|
||||
: fOwnsStatements(ownsStatements)
|
||||
{
|
||||
}
|
||||
|
||||
StatementList::~StatementList()
|
||||
{
|
||||
if (fOwnsStatements) {
|
||||
for (int32 i = 0; i < Size(); i ++) {
|
||||
Statement* statement = StatementAt(i);
|
||||
delete statement;
|
||||
}
|
||||
}
|
||||
fList.MakeEmpty();
|
||||
}
|
||||
|
||||
void StatementList::Add(Statement* statement)
|
||||
{
|
||||
fList.AddItem(statement);
|
||||
}
|
||||
|
||||
void StatementList::Remove(Statement* statement)
|
||||
{
|
||||
fList.RemoveItem(statement);
|
||||
}
|
||||
|
||||
int32 StatementList::Size()
|
||||
{
|
||||
return fList.CountItems();
|
||||
}
|
||||
|
||||
Statement* StatementList::StatementAt(int32 index)
|
||||
{
|
||||
return (Statement*)fList.ItemAt(index);
|
||||
}
|
||||
|
||||
Statement* StatementList::GetStatement(const char* keyword)
|
||||
{
|
||||
for (int32 i = 0; i < fList.CountItems(); i ++) {
|
||||
if (strcmp(keyword, StatementAt(i)->GetKeywordString()) == 0) {
|
||||
return StatementAt(i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* StatementList::GetValue(const char* keyword)
|
||||
{
|
||||
Statement* statement = GetStatement(keyword);
|
||||
if (statement != NULL) {
|
||||
return statement->GetValueString();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void StatementList::Print()
|
||||
{
|
||||
for (int32 i = 0; i < Size(); i ++) {
|
||||
StatementAt(i)->Print();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _STATEMENT_LIST_H
|
||||
#define _STATEMENT_LIST_H
|
||||
|
||||
#include <List.h>
|
||||
|
||||
class Statement;
|
||||
|
||||
class StatementList {
|
||||
private:
|
||||
BList fList;
|
||||
bool fOwnsStatements;
|
||||
|
||||
public:
|
||||
StatementList(bool ownsStatements);
|
||||
~StatementList();
|
||||
|
||||
void Add(Statement* statement);
|
||||
void Remove(Statement* statement);
|
||||
int32 Size();
|
||||
Statement* StatementAt(int32 index);
|
||||
|
||||
Statement* GetStatement(const char* keyword);
|
||||
const char* GetValue(const char* keyword);
|
||||
|
||||
void Print();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "StatementListVisitor.h"
|
||||
|
||||
void StatementListVisitor::Visit(StatementList* list)
|
||||
{
|
||||
if (list == NULL) return;
|
||||
|
||||
const int32 n = list->Size();
|
||||
for (int32 i = 0; i < n; i ++) {
|
||||
Statement* statement = list->StatementAt(i);
|
||||
GroupStatement group(statement);
|
||||
if (group.IsOpenGroup()) {
|
||||
BeginGroup(&group);
|
||||
fLevel ++;
|
||||
} else if (statement->IsValueStatement()) {
|
||||
DoValue(statement);
|
||||
} else if (statement->IsDefaultStatement()) {
|
||||
DoDefault(statement);
|
||||
} else if (statement->IsQueryStatement()) {
|
||||
DoQuery(statement);
|
||||
} else if (statement->IsParamStatement()) {
|
||||
DoParam(statement);
|
||||
}
|
||||
|
||||
StatementList* children = statement->GetChildren();
|
||||
if (children != NULL) {
|
||||
Visit(children);
|
||||
}
|
||||
|
||||
// Close statements have been removed
|
||||
if (group.IsOpenGroup()) {
|
||||
fLevel --;
|
||||
EndGroup(&group);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _STATEMENT_LIST_VISITOR_H
|
||||
#define _STATEMENT_LIST_VISITOR_H
|
||||
|
||||
#include "StatementWrapper.h"
|
||||
#include "StatementList.h"
|
||||
|
||||
class StatementListVisitor {
|
||||
private:
|
||||
int32 fLevel;
|
||||
public:
|
||||
StatementListVisitor() : fLevel(0) {}
|
||||
virtual ~StatementListVisitor() {}
|
||||
|
||||
virtual void Visit(StatementList* list);
|
||||
|
||||
// the nesting level
|
||||
int32 GetLevel() const { return fLevel; }
|
||||
|
||||
virtual void BeginGroup(GroupStatement* group) {};
|
||||
virtual void DoDefault(Statement* statement) {};
|
||||
virtual void DoQuery(Statement* statement) {};
|
||||
virtual void DoValue(Statement* statement) {};
|
||||
virtual void DoParam(Statement* statement) {};
|
||||
virtual void EndGroup(GroupStatement* group) {};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "StatementWrapper.h"
|
||||
|
||||
static const char* kOpenUIStatement = "OpenUI";
|
||||
static const char* kCloseUIStatement = "CloseUI";
|
||||
|
||||
static const char* kOpenGroupStatement = "OpenGroup";
|
||||
static const char* kCloseGroupStatement = "CloseGroup";
|
||||
static const char* kOpenSubGroupStatement = "OpenSubGroup";
|
||||
static const char* kCloseSubGroupStatement = "CloseSubGroup";
|
||||
|
||||
// JCL
|
||||
static const char* kJCL = "JCL";
|
||||
static const char* kJCLOpenUIStatement = "JCLOpenUI";
|
||||
static const char* kJCLCloseUIStatement = "JCLCloseUI";
|
||||
|
||||
|
||||
StatementWrapper::StatementWrapper(Statement* statement)
|
||||
: fStatement(statement)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
GroupStatement::GroupStatement(Statement* statement)
|
||||
: StatementWrapper(statement)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
bool GroupStatement::IsUIGroup()
|
||||
{
|
||||
return strcmp(GetKeyword(), kOpenUIStatement) == 0;
|
||||
}
|
||||
|
||||
bool GroupStatement::IsGroup()
|
||||
{
|
||||
return strcmp(GetKeyword(), kOpenGroupStatement) == 0;
|
||||
}
|
||||
|
||||
bool GroupStatement::IsSubGroup()
|
||||
{
|
||||
return strcmp(GetKeyword(), kOpenSubGroupStatement) == 0;
|
||||
}
|
||||
|
||||
bool GroupStatement::IsJCL()
|
||||
{
|
||||
return strstr(GetKeyword(), kJCL) == GetKeyword();
|
||||
}
|
||||
|
||||
bool GroupStatement::IsOpenGroup()
|
||||
{
|
||||
const char* keyword = GetKeyword();
|
||||
|
||||
return strcmp(keyword, kOpenUIStatement) == 0 ||
|
||||
strcmp(keyword, kOpenGroupStatement) == 0 ||
|
||||
strcmp(keyword, kOpenSubGroupStatement) == 0 ||
|
||||
strcmp(keyword, kJCLOpenUIStatement) == 0;
|
||||
}
|
||||
|
||||
bool GroupStatement::IsCloseGroup()
|
||||
{
|
||||
const char* keyword = GetKeyword();
|
||||
|
||||
return strcmp(keyword, kCloseUIStatement) == 0 ||
|
||||
strcmp(keyword, kCloseGroupStatement) == 0 ||
|
||||
strcmp(keyword, kCloseSubGroupStatement) == 0 ||
|
||||
strcmp(keyword, kJCLCloseUIStatement) == 0;
|
||||
}
|
||||
|
||||
Value* GroupStatement::GetValue()
|
||||
{
|
||||
if (strcmp(GetKeyword(), kOpenUIStatement) == 0 ||
|
||||
strcmp(GetKeyword(), kJCLOpenUIStatement) == 0) {
|
||||
return GetStatement()->GetOption();
|
||||
} else {
|
||||
return GetStatement()->GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
const char* GroupStatement::GetGroupName()
|
||||
{
|
||||
Value* value = GetValue();
|
||||
if (value == NULL) return NULL;
|
||||
BString* string = value->GetValue();
|
||||
if (string == NULL) return NULL;
|
||||
const char* name = string->String();
|
||||
if (name != NULL && *name == '*') {
|
||||
// skip '*'
|
||||
name ++;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
const char* GroupStatement::GetGroupTranslation()
|
||||
{
|
||||
Value* value = GetValue();
|
||||
if (value == NULL) return NULL;
|
||||
BString* string = value->GetTranslation();
|
||||
if (string == NULL) return NULL;
|
||||
return string->String();
|
||||
}
|
||||
|
||||
GroupStatement::Type GroupStatement::GetType()
|
||||
{
|
||||
const char* type = GetStatement()->GetValueString();
|
||||
if (type == NULL) return kUnknown;
|
||||
|
||||
if (strstr(type, "PickOne") != NULL) return kPickOne;
|
||||
if (strstr(type, "PickMany") != NULL) return kPickMany;
|
||||
if (strstr(type, "Boolean") != NULL) return kBoolean;
|
||||
|
||||
return kUnknown;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _STATEMENT_WRAPPER_H
|
||||
#define _STATEMENT_WRAPPER_H
|
||||
|
||||
#include "Statement.h"
|
||||
|
||||
// wrapper classes to provide specific access to
|
||||
// statement members
|
||||
|
||||
class StatementWrapper
|
||||
{
|
||||
private:
|
||||
Statement* fStatement;
|
||||
|
||||
public:
|
||||
StatementWrapper(Statement* statement);
|
||||
|
||||
Statement* GetStatement() { return fStatement; }
|
||||
const char* GetKeyword() { return fStatement->GetKeyword()->String(); }
|
||||
};
|
||||
|
||||
class GroupStatement : public StatementWrapper
|
||||
{
|
||||
private:
|
||||
Value* GetValue();
|
||||
|
||||
public:
|
||||
GroupStatement(Statement* statement);
|
||||
|
||||
// test methods if the wrapped statement is a group statement
|
||||
bool IsUIGroup();
|
||||
bool IsGroup();
|
||||
bool IsSubGroup();
|
||||
|
||||
bool IsOpenGroup();
|
||||
bool IsCloseGroup();
|
||||
|
||||
bool IsJCL();
|
||||
|
||||
// accessors
|
||||
const char* GetGroupName();
|
||||
const char* GetGroupTranslation();
|
||||
|
||||
enum Type {
|
||||
kPickOne,
|
||||
kPickMany,
|
||||
kBoolean,
|
||||
kUnknown
|
||||
};
|
||||
|
||||
Type GetType();
|
||||
};
|
||||
|
||||
class ConstraintsStatement : public StatementWrapper
|
||||
{
|
||||
public:
|
||||
ConstraintsStatement(Statement* statement);
|
||||
|
||||
// is this realy a constraints statement
|
||||
bool IsConstraints();
|
||||
|
||||
const char* GetFirstKeyword();
|
||||
const char* GetFirstOption();
|
||||
const char* GetSecondKeyword();
|
||||
const char* GetSecondOption();
|
||||
};
|
||||
|
||||
class OrderDependencyStatement : public StatementWrapper
|
||||
{
|
||||
public:
|
||||
OrderDependencyStatement(Statement* statement);
|
||||
|
||||
// is this realy a order dependency statement
|
||||
bool IsOrderDependency();
|
||||
|
||||
// is this a NonUIOrderDependencyStatement
|
||||
bool IsNonUI();
|
||||
|
||||
float GetOrder();
|
||||
const char* GetSection();
|
||||
const char* GetKeyword();
|
||||
const char* GetOption();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "Value.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
Value::Value(BString* value, Type type)
|
||||
: fType(type)
|
||||
, fValue(value)
|
||||
, fTranslation(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Value::~Value()
|
||||
{
|
||||
delete fValue;
|
||||
delete fTranslation;
|
||||
}
|
||||
|
||||
void Value::SetType(Type type)
|
||||
{
|
||||
fType = type;
|
||||
}
|
||||
|
||||
Value::Type Value::GetType()
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
void Value::SetValue(BString* value)
|
||||
{
|
||||
fValue = value;
|
||||
}
|
||||
|
||||
BString* Value::GetValue()
|
||||
{
|
||||
return fValue;
|
||||
}
|
||||
|
||||
void Value::SetTranslation(BString* translation)
|
||||
{
|
||||
fTranslation = translation;
|
||||
}
|
||||
|
||||
BString* Value::GetTranslation()
|
||||
{
|
||||
return fTranslation;
|
||||
}
|
||||
|
||||
const char* Value::GetValueString()
|
||||
{
|
||||
if (fValue != NULL) {
|
||||
return fValue->String();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* Value::GetTranslationString()
|
||||
{
|
||||
if (fTranslation != NULL) {
|
||||
return fTranslation->String();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* Value::ElementForType()
|
||||
{
|
||||
switch (fType) {
|
||||
case kSymbolValue: return "Symbol";
|
||||
break;
|
||||
case kStringValue: return "String";
|
||||
break;
|
||||
case kInvocationValue: return "Invocation";
|
||||
break;
|
||||
case kQuotedValue: return "Quoted";
|
||||
break;
|
||||
case kUnknownValue: return "Unknown";
|
||||
break;
|
||||
}
|
||||
return "NULL";
|
||||
}
|
||||
|
||||
void Value::Print()
|
||||
{
|
||||
printf("\t\t<%s>\n", ElementForType());
|
||||
if (fValue != NULL) {
|
||||
printf("\t\t\t<value>%s</value>\n", fValue->String());
|
||||
}
|
||||
|
||||
if (fTranslation != NULL) {
|
||||
printf("\t\t\t<translation>%s</translation>\n", fTranslation->String());
|
||||
}
|
||||
printf("\t\t</%s>\n", ElementForType());
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _VALUE_H
|
||||
#define _VALUE_H
|
||||
|
||||
#include <String.h>
|
||||
|
||||
class Value {
|
||||
public:
|
||||
enum Type {
|
||||
kSymbolValue,
|
||||
kStringValue,
|
||||
kInvocationValue,
|
||||
kQuotedValue,
|
||||
kUnknownValue
|
||||
};
|
||||
|
||||
private:
|
||||
Type fType;
|
||||
BString* fValue;
|
||||
BString* fTranslation;
|
||||
|
||||
const char* ElementForType();
|
||||
|
||||
public:
|
||||
Value(BString* value = NULL, Type type = kUnknownValue);
|
||||
virtual ~Value();
|
||||
|
||||
void SetType(Type type);
|
||||
Type GetType();
|
||||
|
||||
// mandatory in a valid statement
|
||||
void SetValue(BString* value);
|
||||
BString* GetValue();
|
||||
|
||||
// optional
|
||||
void SetTranslation(BString* translation);
|
||||
BString* GetTranslation();
|
||||
|
||||
// convenience methods
|
||||
const char* GetValueString();
|
||||
const char* GetTranslationString();
|
||||
|
||||
void Print();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _CHARACTER_CLASSES_H
|
||||
#define _CHARACTER_CLASSES_H
|
||||
|
||||
#define kCr '\n'
|
||||
#define kLf '\r'
|
||||
#define kTab '\t'
|
||||
#define kEof -1
|
||||
|
||||
inline bool IsWhitespaceSeparator(int ch)
|
||||
{
|
||||
return ch == ' ' || ch == kTab;
|
||||
}
|
||||
|
||||
inline bool IsWhitespace(int ch)
|
||||
{
|
||||
return ch == ' ' || ch == kTab || ch == kLf || ch == kCr;
|
||||
}
|
||||
|
||||
inline bool IsIdentChar(int ch) {
|
||||
// TODO check '.' if is an identifier character
|
||||
// in one of the PPD files delivered with BeOS R5
|
||||
// '.' is used inside of an identifier
|
||||
// if (ch == '.' || ch == '/' || ch == ':') return false;
|
||||
if (ch == '/' || ch == ':') return false;
|
||||
return 33 <= ch && ch <= 126;
|
||||
}
|
||||
|
||||
inline bool IsOptionChar(int ch)
|
||||
{
|
||||
if (ch == '.') return true;
|
||||
return IsIdentChar(ch);
|
||||
}
|
||||
|
||||
inline bool IsChar(int ch)
|
||||
{
|
||||
if (ch == '"') return false;
|
||||
return 32 <= ch && ch <= 255 || IsWhitespace(ch);
|
||||
}
|
||||
|
||||
inline bool IsPrintableWithoutWhitespaces(int ch)
|
||||
{
|
||||
if (ch == '"') return false;
|
||||
return 33 <= ch && ch <= 126;
|
||||
}
|
||||
|
||||
inline bool IsPrintableWithWhitespaces(int ch)
|
||||
{
|
||||
return IsPrintableWithoutWhitespaces(ch) || IsWhitespace(ch);
|
||||
}
|
||||
|
||||
inline bool IsStringChar(int ch)
|
||||
{
|
||||
if (IsWhitespaceSeparator(ch)) return true;
|
||||
if (ch == '"') return true;
|
||||
if (ch == '/') return false;
|
||||
return IsPrintableWithoutWhitespaces(ch);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
SubDir HAIKU_TOP src tests add-ons print ppd parser ;
|
||||
|
||||
# SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src tests add-ons print ppd model ;
|
||||
SubDirHdrs $(HAIKU_TOP) src tests add-ons print ppd shared ;
|
||||
|
||||
StaticLibrary libppdtest.a :
|
||||
Parser.cpp
|
||||
PPDFile.cpp
|
||||
PPDParser.cpp
|
||||
Scanner.cpp
|
||||
;
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "CharacterClasses.h"
|
||||
#include "Scanner.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int FileBuffer::Read()
|
||||
{
|
||||
if (fIndex >= fSize) {
|
||||
fSize = fFile->Read(fBuffer, kReadBufferSize);
|
||||
fIndex = 0;
|
||||
}
|
||||
if (fSize <= 0) {
|
||||
return -1;
|
||||
}
|
||||
return (int)fBuffer[fIndex ++];
|
||||
}
|
||||
|
||||
PPDFile::PPDFile(const char* file, PPDFile* previousFile)
|
||||
: fFileName(file)
|
||||
, fFile(file, B_READ_ONLY)
|
||||
, fPreviousFile(previousFile)
|
||||
, fCurrentPosition(0, 1)
|
||||
, fCurrentChar(-1)
|
||||
, fBuffer(&fFile)
|
||||
{
|
||||
}
|
||||
|
||||
PPDFile::~PPDFile()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
status_t PPDFile::InitCheck()
|
||||
{
|
||||
return fFile.InitCheck();
|
||||
}
|
||||
|
||||
int PPDFile::GetCurrentChar()
|
||||
{
|
||||
return fCurrentChar;
|
||||
}
|
||||
|
||||
void PPDFile::NextChar() {
|
||||
fCurrentChar = fBuffer.Read();
|
||||
if (fCurrentChar != -1) {
|
||||
#if TRACE_SCANNER
|
||||
fprintf(stderr, "%c ", fCurrentChar);
|
||||
#endif
|
||||
if (fCurrentChar == kCr) {
|
||||
fCurrentPosition.x = 0;
|
||||
fCurrentPosition.y ++;
|
||||
} else {
|
||||
fCurrentPosition.x ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Position PPDFile::GetPosition()
|
||||
{
|
||||
return fCurrentPosition;
|
||||
}
|
||||
|
||||
PPDFile* PPDFile::GetPreviousFile()
|
||||
{
|
||||
return fPreviousFile;
|
||||
}
|
||||
|
||||
const char* PPDFile::GetFileName()
|
||||
{
|
||||
return fFileName.String();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _PPD_FILE_H
|
||||
#define _PPD_FILE_H
|
||||
|
||||
#include <File.h>
|
||||
#include <String.h>
|
||||
|
||||
class Position {
|
||||
public:
|
||||
int x;
|
||||
int y;
|
||||
Position() : x(0), y(0) {}
|
||||
Position(int x, int y) : x(x), y(y) {}
|
||||
};
|
||||
|
||||
#define kReadBufferSize 1024
|
||||
|
||||
class FileBuffer {
|
||||
BFile* fFile;
|
||||
|
||||
unsigned char fBuffer[kReadBufferSize];
|
||||
int fIndex;
|
||||
int fSize;
|
||||
|
||||
public:
|
||||
FileBuffer(BFile* file) : fFile(file), fIndex(0), fSize(0) {}
|
||||
int Read();
|
||||
};
|
||||
|
||||
class PPDFile {
|
||||
private:
|
||||
BString fFileName;
|
||||
BFile fFile;
|
||||
PPDFile* fPreviousFile; // single linked list of PPD files (stack)
|
||||
Position fCurrentPosition;
|
||||
int fCurrentChar;
|
||||
FileBuffer fBuffer;
|
||||
|
||||
public:
|
||||
// Opens the file for reading. Use IsValid to check if the file could
|
||||
// be opened successfully.
|
||||
// PPDFile also maintance a single linked list. The parameter previousFile
|
||||
// can be used to store a reference to a previous file.
|
||||
PPDFile(const char* file, PPDFile* previousFile = NULL);
|
||||
// Closes the file.
|
||||
~PPDFile();
|
||||
|
||||
// Returns the status of the constructor.
|
||||
status_t InitCheck();
|
||||
|
||||
// Returns the current character or -1 if on EOF.
|
||||
int GetCurrentChar();
|
||||
// Reads the next character. Use GetChar to read the current
|
||||
void NextChar();
|
||||
// Returns the position of the current character.
|
||||
Position GetPosition();
|
||||
// The previous file from the constructor.
|
||||
PPDFile* GetPreviousFile();
|
||||
// Returns the file name
|
||||
const char* GetFileName();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "PPDParser.h"
|
||||
|
||||
#include "AutoDelete.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// #define VERBOSE 1
|
||||
|
||||
struct Keyword {
|
||||
const char* name;
|
||||
const char* since;
|
||||
int major;
|
||||
int minor;
|
||||
bool found;
|
||||
};
|
||||
|
||||
static const Keyword gRequiredKeywords[] = {
|
||||
{"DefaultImageableArea", NULL},
|
||||
{"DefaultPageRegion", NULL},
|
||||
{"DefaultPageSize", NULL},
|
||||
{"DefaultPaperDimension", NULL},
|
||||
// sometimes missing
|
||||
// {"FileVersion", NULL},
|
||||
//
|
||||
// {"FormatVersion", NULL},
|
||||
{"ImageableArea", NULL},
|
||||
// "since" is not specified in standard!
|
||||
{"LanguageEncoding", "4.3"},
|
||||
{"LanguageVersion", NULL},
|
||||
{"Manufacturer", "4.3"},
|
||||
{"ModelName", NULL},
|
||||
{"NickName", NULL},
|
||||
{"PageRegion", NULL},
|
||||
{"PageSize", NULL},
|
||||
{"PaperDimension", NULL},
|
||||
{"PCFileName", NULL},
|
||||
{"PPD-Adobe", NULL},
|
||||
{"Product", NULL},
|
||||
{"PSVersion", NULL},
|
||||
// sometimes missing
|
||||
// {"ShortNickName", "4.3"},
|
||||
};
|
||||
|
||||
// e.g. *PPD.Adobe: "4.3"
|
||||
const char* kPPDAdobe = "PPD-Adobe";
|
||||
|
||||
#define NUMBER_OF_REQUIRED_KEYWORDS (int)(sizeof(gRequiredKeywords) / sizeof(struct Keyword))
|
||||
|
||||
class RequiredKeywords
|
||||
{
|
||||
private:
|
||||
Keyword fKeywords[NUMBER_OF_REQUIRED_KEYWORDS];
|
||||
bool fGotVersion;
|
||||
int fMajorVersion;
|
||||
int fMinorVersion;
|
||||
|
||||
void ExtractVersion(int& major, int& minor, const char* version);
|
||||
bool IsVersionRequired(Keyword* keyword);
|
||||
|
||||
public:
|
||||
RequiredKeywords();
|
||||
bool IsRequired(Statement* statement);
|
||||
bool IsComplete();
|
||||
void AppendMissing(BString* string);
|
||||
};
|
||||
|
||||
RequiredKeywords::RequiredKeywords()
|
||||
: fGotVersion(false)
|
||||
{
|
||||
for (int i = 0; i < NUMBER_OF_REQUIRED_KEYWORDS; i ++) {
|
||||
fKeywords[i] = gRequiredKeywords[i];
|
||||
fKeywords[i].found = false;
|
||||
const char* since = fKeywords[i].since;
|
||||
if (since != NULL) {
|
||||
ExtractVersion(fKeywords[i].major, fKeywords[i].minor, since);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RequiredKeywords::ExtractVersion(int& major, int& minor, const char* version)
|
||||
{
|
||||
major = atoi(version);
|
||||
minor = 0;
|
||||
version = strchr(version, '.');
|
||||
if (version != NULL) {
|
||||
version ++;
|
||||
minor = atoi(version);
|
||||
}
|
||||
}
|
||||
|
||||
bool RequiredKeywords::IsVersionRequired(Keyword* keyword)
|
||||
{
|
||||
if (keyword->since == NULL) return true;
|
||||
// be conservative if version is missing
|
||||
if (!fGotVersion) return true;
|
||||
// keyword is not required if file version < since
|
||||
if (fMajorVersion < keyword->major) return false;
|
||||
if (fMajorVersion == keyword->major &&
|
||||
fMinorVersion < keyword->minor) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RequiredKeywords::IsRequired(Statement* statement)
|
||||
{
|
||||
const char* keyword = statement->GetKeyword()->String();
|
||||
|
||||
if (!fGotVersion && strcmp(kPPDAdobe, keyword) == 0 &&
|
||||
statement->GetValue() != NULL) {
|
||||
Value* value = statement->GetValue();
|
||||
BString* string = value->GetValue();
|
||||
fGotVersion = true;
|
||||
ExtractVersion(fMajorVersion, fMinorVersion, string->String());
|
||||
}
|
||||
|
||||
BString defaultKeyword;
|
||||
if (statement->GetType() == Statement::kDefault) {
|
||||
defaultKeyword << "Default" << keyword;
|
||||
keyword = defaultKeyword.String();
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_REQUIRED_KEYWORDS; i ++) {
|
||||
const char* name = fKeywords[i].name;
|
||||
if (strcmp(name, keyword) == 0) {
|
||||
fKeywords[i].found = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RequiredKeywords::IsComplete()
|
||||
{
|
||||
for (int i = 0; i < NUMBER_OF_REQUIRED_KEYWORDS; i ++) {
|
||||
if (!fKeywords[i].found && IsVersionRequired(&fKeywords[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RequiredKeywords::AppendMissing(BString* string)
|
||||
{
|
||||
for (int i = 0; i < NUMBER_OF_REQUIRED_KEYWORDS; i ++) {
|
||||
if (!fKeywords[i].found && IsVersionRequired(&fKeywords[i])) {
|
||||
*string << "Keyword " << fKeywords[i].name;
|
||||
if (fKeywords[i].since != NULL) {
|
||||
*string << fKeywords[i].major << ". " << fKeywords[i].minor
|
||||
<< " < " <<
|
||||
fMajorVersion << "." << fMinorVersion << " ";
|
||||
}
|
||||
*string << " is missing\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Constants
|
||||
|
||||
static const char* kEndStatement = "End";
|
||||
|
||||
// Implementation
|
||||
|
||||
PPDParser::PPDParser(const char* file)
|
||||
: Parser(file)
|
||||
, fStack(false)
|
||||
, fRequiredKeywords(new RequiredKeywords)
|
||||
{
|
||||
}
|
||||
|
||||
PPDParser::~PPDParser()
|
||||
{
|
||||
delete fRequiredKeywords;
|
||||
}
|
||||
|
||||
void PPDParser::Push(Statement* statement)
|
||||
{
|
||||
fStack.Add(statement);
|
||||
}
|
||||
|
||||
Statement* PPDParser::Top()
|
||||
{
|
||||
if (fStack.Size() > 0) {
|
||||
return fStack.StatementAt(fStack.Size()-1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PPDParser::Pop()
|
||||
{
|
||||
fStack.Remove(Top());
|
||||
}
|
||||
|
||||
void PPDParser::AddStatement(Statement* statement)
|
||||
{
|
||||
fRequiredKeywords->IsRequired(statement);
|
||||
|
||||
Statement* top = Top();
|
||||
if (top != NULL) {
|
||||
top->AddChild(statement);
|
||||
} else {
|
||||
fPPD->Add(statement);
|
||||
}
|
||||
}
|
||||
|
||||
bool PPDParser::IsValidOpenStatement(GroupStatement* statement)
|
||||
{
|
||||
if (statement->GetGroupName() == NULL) {
|
||||
Error("Missing group ID in open statement");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PPDParser::IsValidCloseStatement(GroupStatement* statement)
|
||||
{
|
||||
if (statement->GetGroupName() == NULL) {
|
||||
Error("Missing option in close statement");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Top() == NULL) {
|
||||
Error("Close statement without an open statement");
|
||||
return false;
|
||||
}
|
||||
|
||||
GroupStatement openStatement(Top());
|
||||
|
||||
// check if corresponding Open* is on top of stack
|
||||
BString open = openStatement.GetKeyword();
|
||||
open.RemoveFirst("Open");
|
||||
BString close = statement->GetKeyword();
|
||||
close.RemoveFirst("Close");
|
||||
|
||||
if (open != close) {
|
||||
Error("Close statement has no corresponding open statement");
|
||||
#ifdef VERBOSE
|
||||
printf("********* OPEN ************\n");
|
||||
openStatement.GetStatement()->Print();
|
||||
printf("********* CLOSE ***********\n");
|
||||
statement->GetStatement()->Print();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
BString openValue(openStatement.GetGroupName());
|
||||
BString closeValue(statement->GetGroupName());
|
||||
|
||||
const char* whiteSpaces = " \t";
|
||||
openValue.RemoveSet(whiteSpaces);
|
||||
closeValue.RemoveSet(whiteSpaces);
|
||||
|
||||
if (openValue != closeValue) {
|
||||
BString message("Open name does not match close name ");
|
||||
message << openValue << " != " << closeValue << "\n";
|
||||
Warning(message.String());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PPDParser::ParseStatement(Statement* _statement)
|
||||
{
|
||||
AutoDelete<Statement> statement(_statement);
|
||||
|
||||
if (_statement->GetKeyword() == NULL) {
|
||||
Error("Keyword missing");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_statement->GetOption() != NULL &&
|
||||
_statement->GetOption()->GetValue() == NULL) {
|
||||
// The parser should not provide an option without a value
|
||||
Error("Option has no value");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_statement->GetValue() != NULL &&
|
||||
_statement->GetValue()->GetValue() == NULL) {
|
||||
// The parser should not provide a value without a value
|
||||
Error("Value has no value");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* keyword = statement.Get()->GetKeyword()->String();
|
||||
if (strcmp(keyword, kEndStatement) == 0) {
|
||||
// End is ignored
|
||||
return true;
|
||||
}
|
||||
|
||||
GroupStatement group(statement.Get());
|
||||
if (group.IsOpenGroup()) {
|
||||
|
||||
if (!IsValidOpenStatement(&group)) {
|
||||
return false;
|
||||
}
|
||||
// Add() has to be infront of Push()!
|
||||
AddStatement(statement.Release());
|
||||
// begin of nested statement
|
||||
Push(statement.Get());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (group.IsCloseGroup()) {
|
||||
|
||||
// end of nested statement
|
||||
if (!IsValidCloseStatement(&group)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Pop();
|
||||
// The closing statement is not stored
|
||||
return true;
|
||||
}
|
||||
|
||||
AddStatement(statement.Release());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PPDParser::ParseStatements()
|
||||
{
|
||||
Statement* statement;
|
||||
while ((statement = Parser::Parse()) != NULL) {
|
||||
#ifdef VERBOSE
|
||||
statement->Print(); fflush(stdout);
|
||||
#endif
|
||||
if (!ParseStatement(statement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fParseAll && fRequiredKeywords->IsComplete()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (HasError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Top() != NULL) {
|
||||
BString error("Missing close statement for:\n");
|
||||
do {
|
||||
error << " * " <<
|
||||
Top()->GetKeywordString() << " " <<
|
||||
Top()->GetOptionString() << "\n";
|
||||
Pop();
|
||||
} while (Top() != NULL);
|
||||
Error(error.String());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PPD* PPDParser::Parse(bool all)
|
||||
{
|
||||
fParseAll = all;
|
||||
|
||||
if (InitCheck() != B_OK) return NULL;
|
||||
|
||||
fPPD = new PPD();
|
||||
|
||||
ParseStatements();
|
||||
|
||||
if (!HasError() && !fRequiredKeywords->IsComplete()) {
|
||||
BString string;
|
||||
fRequiredKeywords->AppendMissing(&string);
|
||||
Error(string.String());
|
||||
}
|
||||
|
||||
if (HasError()) {
|
||||
delete fPPD; fPPD = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fPPD;
|
||||
}
|
||||
|
||||
PPD* PPDParser::ParseAll()
|
||||
{
|
||||
return Parse(true);
|
||||
}
|
||||
|
||||
PPD* PPDParser::ParseHeader()
|
||||
{
|
||||
return Parse(false);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _PPD_PARSER_H
|
||||
#define _PPD_PARSER_H
|
||||
|
||||
#include "PPD.h"
|
||||
#include "Parser.h"
|
||||
#include "Statement.h"
|
||||
#include "StatementWrapper.h"
|
||||
|
||||
class RequiredKeywords;
|
||||
|
||||
class PPDParser : public Parser
|
||||
{
|
||||
private:
|
||||
PPD* fPPD;
|
||||
StatementList fStack; // of nested statements
|
||||
RequiredKeywords* fRequiredKeywords;
|
||||
bool fParseAll;
|
||||
|
||||
void Push(Statement* statement);
|
||||
Statement* Top();
|
||||
void Pop();
|
||||
|
||||
// Add statement to PPD or the children of a
|
||||
// nested statement
|
||||
void AddStatement(Statement* statement);
|
||||
|
||||
bool IsValidOpenStatement(GroupStatement* statement);
|
||||
bool IsValidCloseStatement(GroupStatement* statement);
|
||||
bool ParseStatement(Statement* statement);
|
||||
bool ParseStatements();
|
||||
PPD* Parse(bool all);
|
||||
|
||||
public:
|
||||
PPDParser(const char* file);
|
||||
~PPDParser();
|
||||
|
||||
PPD* ParseAll();
|
||||
PPD* ParseHeader();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "AutoDelete.h"
|
||||
#include "CharacterClasses.h"
|
||||
#include "Parser.h"
|
||||
|
||||
Parser::Parser(const char* file)
|
||||
: fScanner(file)
|
||||
{
|
||||
if (InitCheck() == B_OK) {
|
||||
NextChar();
|
||||
}
|
||||
}
|
||||
|
||||
status_t Parser::InitCheck()
|
||||
{
|
||||
return fScanner.InitCheck();
|
||||
}
|
||||
|
||||
void Parser::SkipWhitespaces()
|
||||
{
|
||||
while (IsWhitespace(GetCurrentChar())) {
|
||||
NextChar();
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::SkipComment()
|
||||
{
|
||||
while (GetCurrentChar() != kEof && GetCurrentChar() != kCr) {
|
||||
NextChar();
|
||||
}
|
||||
NextChar();
|
||||
}
|
||||
|
||||
void Parser::SkipWhitespaceSeparator()
|
||||
{
|
||||
while (IsWhitespaceSeparator(GetCurrentChar())) {
|
||||
NextChar();
|
||||
}
|
||||
}
|
||||
|
||||
bool Parser::ParseKeyword(Statement* statement)
|
||||
{
|
||||
// ["?"]
|
||||
if (GetCurrentChar() == '?') {
|
||||
NextChar();
|
||||
statement->SetType(Statement::kQuery);
|
||||
}
|
||||
// Keyword
|
||||
BString* keyword = fScanner.ScanIdent();
|
||||
if (keyword == NULL) {
|
||||
Error("Identifier expected");
|
||||
return false;
|
||||
}
|
||||
statement->SetKeyword(keyword);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ParseTranslation(Value* value, int separator)
|
||||
{
|
||||
BString* translation = fScanner.ScanTranslationValue(separator);
|
||||
if (translation == NULL) {
|
||||
Error("Out of memory scanning translationn!");
|
||||
return false;
|
||||
}
|
||||
value->SetTranslation(translation);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ParseOption(Statement* statement)
|
||||
{
|
||||
// ["^"]
|
||||
bool isSymbolValue = GetCurrentChar() == '^';
|
||||
if (isSymbolValue) {
|
||||
NextChar();
|
||||
}
|
||||
|
||||
// [ ... Option ...]
|
||||
if (IsOptionChar(GetCurrentChar())) {
|
||||
|
||||
BString* option = fScanner.ScanOption();
|
||||
if (option == NULL) {
|
||||
Error("Out of memory scanning option!");
|
||||
return false;
|
||||
}
|
||||
Value::Type type;
|
||||
if (isSymbolValue) {
|
||||
type = Value::kSymbolValue;
|
||||
} else {
|
||||
type = Value::kStringValue;
|
||||
}
|
||||
Value* value = new Value(option, type);
|
||||
statement->SetOption(value);
|
||||
|
||||
SkipWhitespaceSeparator();
|
||||
// ["/" Translation ]
|
||||
if (GetCurrentChar() == '/') {
|
||||
NextChar();
|
||||
return ParseTranslation(value, ':');
|
||||
}
|
||||
} else {
|
||||
if (isSymbolValue) {
|
||||
Error("Expected symbol value!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ParseValue(Statement* statement)
|
||||
{
|
||||
if (GetCurrentChar() == '"') {
|
||||
NextChar();
|
||||
|
||||
// "..."
|
||||
AutoDelete<Value> value(new Value());
|
||||
|
||||
BString* string;
|
||||
if (statement->GetOption() != NULL) {
|
||||
string = fScanner.ScanInvocationValue();
|
||||
value.Get()->SetType(Value::kInvocationValue);
|
||||
} else {
|
||||
string = fScanner.ScanQuotedValue();
|
||||
value.Get()->SetType(Value::kQuotedValue);
|
||||
}
|
||||
|
||||
if (string == NULL) {
|
||||
Error("Expected value");
|
||||
return false;
|
||||
}
|
||||
|
||||
// " is expected
|
||||
if (GetCurrentChar() != '"') {
|
||||
Error("Expected \" at end of value");
|
||||
return false;
|
||||
}
|
||||
NextChar();
|
||||
|
||||
value.Get()->SetValue(string);
|
||||
statement->SetValue(value.Release());
|
||||
} else if (GetCurrentChar() == '^') {
|
||||
// ^ SymbolValue
|
||||
BString* symbol = fScanner.ScanOption();
|
||||
if (symbol == NULL) {
|
||||
Error("Symbol expected!");
|
||||
return false;
|
||||
}
|
||||
Value* value = new Value(symbol, Value::kSymbolValue);
|
||||
statement->SetValue(value);
|
||||
} else {
|
||||
// StringValue
|
||||
BString* stringValue = fScanner.ScanStringValue();
|
||||
if (stringValue == NULL) {
|
||||
Error("String value expected!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Value* value = new Value(stringValue, Value::kStringValue);
|
||||
statement->SetValue(value);
|
||||
}
|
||||
if (GetCurrentChar() == '/') {
|
||||
NextChar();
|
||||
return ParseTranslation(statement->GetValue(), kCr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Parser::UpdateStatementType(Statement* statement)
|
||||
{
|
||||
if (statement->GetType() != Statement::kUnknown) return;
|
||||
|
||||
BString* keyword = statement->GetKeyword();
|
||||
Statement::Type type;
|
||||
if (keyword->FindFirst("Default") == 0) {
|
||||
type = Statement::kDefault;
|
||||
keyword->RemoveFirst("Default");
|
||||
} else if (keyword->FindFirst("Param") == 0) {
|
||||
type = Statement::kParam;
|
||||
keyword->RemoveFirst("Param");
|
||||
} else {
|
||||
type = Statement::kValue;
|
||||
}
|
||||
statement->SetType(type);
|
||||
}
|
||||
|
||||
// ["?"]Keyword [["^"]Option["/"Translation]]
|
||||
// [":"
|
||||
// ["^"]Value ["/" Translation].
|
||||
// ]
|
||||
Statement* Parser::ParseStatement()
|
||||
{
|
||||
AutoDelete<Statement> statement(new Statement());
|
||||
|
||||
if (!ParseKeyword(statement.Get())) {
|
||||
return NULL;
|
||||
}
|
||||
SkipWhitespaceSeparator();
|
||||
|
||||
if (!ParseOption(statement.Get())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SkipWhitespaceSeparator();
|
||||
// [":" ... ]
|
||||
if (GetCurrentChar() == ':') {
|
||||
NextChar();
|
||||
SkipWhitespaceSeparator();
|
||||
if (!ParseValue(statement.Get())) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
SkipWhitespaceSeparator();
|
||||
if (GetCurrentChar() == kEof || GetCurrentChar() == kLf || GetCurrentChar() == kCr) {
|
||||
UpdateStatementType(statement.Get());
|
||||
Statement* result = statement.Release();
|
||||
return result;
|
||||
} else {
|
||||
Error("Newline expected at end of statement");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Statement* Parser::Parse()
|
||||
{
|
||||
while (true) {
|
||||
int ch = GetCurrentChar();
|
||||
if (ch == -1) {
|
||||
return NULL;
|
||||
}
|
||||
if (IsWhitespace(ch)) {
|
||||
SkipWhitespaces();
|
||||
} else if (ch == '*') {
|
||||
// begin of comment or statement
|
||||
NextChar();
|
||||
ch = GetCurrentChar();
|
||||
if (ch == '%') {
|
||||
SkipComment();
|
||||
} else {
|
||||
return ParseStatement();
|
||||
}
|
||||
} else {
|
||||
Error("Expected *");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _PARSER_H
|
||||
#define _PARSER_H
|
||||
|
||||
#include "Scanner.h"
|
||||
#include "Statement.h"
|
||||
|
||||
// PPD statement parser
|
||||
class Parser
|
||||
{
|
||||
private:
|
||||
Scanner fScanner;
|
||||
|
||||
int GetCurrentChar() { return fScanner.GetCurrentChar(); }
|
||||
void NextChar() { fScanner.NextChar(); }
|
||||
|
||||
void SkipWhitespaces();
|
||||
void SkipComment();
|
||||
void SkipWhitespaceSeparator();
|
||||
bool ParseKeyword(Statement* statement);
|
||||
bool ParseTranslation(Value* value, int separator = -1);
|
||||
bool ParseOption(Statement* statement);
|
||||
bool ParseValue(Statement* statement);
|
||||
void UpdateStatementType(Statement* statement);
|
||||
Statement* ParseStatement();
|
||||
|
||||
protected:
|
||||
void Warning(const char* message) { fScanner.Warning(message); }
|
||||
void Error(const char* message) { fScanner.Error(message); }
|
||||
|
||||
public:
|
||||
// Initializes the parser with the file
|
||||
Parser(const char* file);
|
||||
// Returns B_OK if the constructor could open the file
|
||||
// successfully
|
||||
status_t InitCheck();
|
||||
|
||||
// Includes the file for parsing
|
||||
bool Include(const char* file) { return fScanner.Include(file); }
|
||||
|
||||
// Returns the statement or null on eof or on error
|
||||
Statement* Parse();
|
||||
// Returns true if there was a parsing error
|
||||
bool HasError() { return fScanner.HasError(); }
|
||||
// The error message of the parsing error
|
||||
const char* GetErrorMessage() { return fScanner.GetErrorMessage(); }
|
||||
// Returns true if there are any warnings
|
||||
bool HasWarning() { return fScanner.HasWarning(); }
|
||||
// Returns the waring message
|
||||
const char* GetWarningMessage() { return fScanner.GetWarningMessage(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "CharacterClasses.h"
|
||||
#include "Scanner.h"
|
||||
|
||||
Scanner::Scanner(const char* file)
|
||||
{
|
||||
fCurrentFile = new PPDFile(file);
|
||||
}
|
||||
|
||||
Scanner::~Scanner()
|
||||
{
|
||||
while (fCurrentFile != NULL) {
|
||||
PPDFile* file = fCurrentFile->GetPreviousFile();
|
||||
delete fCurrentFile;
|
||||
fCurrentFile = file;
|
||||
}
|
||||
}
|
||||
|
||||
status_t Scanner::InitCheck()
|
||||
{
|
||||
return fCurrentFile->InitCheck();
|
||||
}
|
||||
|
||||
void Scanner::Warning(const char* message)
|
||||
{
|
||||
fWarnings << "Line " << GetPosition().y <<
|
||||
", column " << GetPosition().x << ": " << message;
|
||||
}
|
||||
|
||||
const char* Scanner::GetWarningMessage()
|
||||
{
|
||||
return fWarnings.String();
|
||||
}
|
||||
|
||||
bool Scanner::HasWarning()
|
||||
{
|
||||
return fWarnings.Length() > 0;
|
||||
}
|
||||
|
||||
void Scanner::Error(const char* message)
|
||||
{
|
||||
fLastError = GetFileName();
|
||||
fLastError << " (line " << GetPosition().y <<
|
||||
", column " << GetPosition().x << "): " <<
|
||||
message;
|
||||
}
|
||||
|
||||
const char* Scanner::GetErrorMessage()
|
||||
{
|
||||
return fLastError.String();
|
||||
}
|
||||
|
||||
bool Scanner::HasError()
|
||||
{
|
||||
const char* message = GetErrorMessage();
|
||||
return message != NULL && strcmp(message, "") != 0;
|
||||
}
|
||||
|
||||
BString* Scanner::Scan(bool (cond)(int ch))
|
||||
{
|
||||
BString* text = new BString();
|
||||
while (cond(GetCurrentChar())) {
|
||||
text->Append(GetCurrentChar(), 1);
|
||||
NextChar();
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
static inline int getHexadecimalDigit(int ch) {
|
||||
if ('0' <= ch && '9' <= ch) {
|
||||
return ch - '0';
|
||||
}
|
||||
if ('a' <= ch || ch <= 'f') {
|
||||
return 10 + ch - 'a';
|
||||
}
|
||||
if ('A' <= ch || ch <= 'F') {
|
||||
return 10 + ch - 'A';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Scanner::ScanHexadecimalSubstring(BString* literal)
|
||||
{
|
||||
int digit = 0;
|
||||
int value = 0;
|
||||
while(true) {
|
||||
NextChar();
|
||||
int ch = GetCurrentChar();
|
||||
|
||||
if (ch == '>') {
|
||||
// end of hexadecimal substring reached
|
||||
return digit == 0;
|
||||
}
|
||||
|
||||
if (ch == -1) {
|
||||
Error("Unexpected EOF in hexadecimal substring!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsWhitespace(ch)) {
|
||||
// ignore white spaces
|
||||
continue;
|
||||
}
|
||||
|
||||
int d = getHexadecimalDigit(ch);
|
||||
if (d == -1) {
|
||||
Error("Character is not a hexadecimal digit!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d == 0) {
|
||||
// first digit
|
||||
value = d << 8;
|
||||
d = 1;
|
||||
} else {
|
||||
// second digit
|
||||
value |= d;
|
||||
literal->Append((unsigned char)value, 1);
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// !quotedValue means Translation String
|
||||
BString* Scanner::ScanLiteral(bool quotedValue, int separator)
|
||||
{
|
||||
BString* literal = new BString();
|
||||
|
||||
while (true) {
|
||||
int ch = GetCurrentChar();
|
||||
if (ch == '<') {
|
||||
if (!ScanHexadecimalSubstring(literal)) {
|
||||
delete literal;
|
||||
return NULL;
|
||||
}
|
||||
} else if (quotedValue && (ch == kLf || ch == kCr)) {
|
||||
// nothing to do
|
||||
} else if (!quotedValue && ch == '"') {
|
||||
// translation string allows '"'
|
||||
} else if (!IsChar(ch) || ch == separator) {
|
||||
return literal;
|
||||
}
|
||||
literal->Append(ch, 1);
|
||||
NextChar();
|
||||
}
|
||||
}
|
||||
|
||||
int Scanner::GetCurrentChar()
|
||||
{
|
||||
if (fCurrentFile != NULL) {
|
||||
return fCurrentFile->GetCurrentChar();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Scanner::NextChar()
|
||||
{
|
||||
if (fCurrentFile != NULL) {
|
||||
fCurrentFile->NextChar();
|
||||
if (fCurrentFile->GetCurrentChar() == kEof) {
|
||||
PPDFile* file = fCurrentFile->GetPreviousFile();
|
||||
delete fCurrentFile;
|
||||
fCurrentFile = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Position Scanner::GetPosition()
|
||||
{
|
||||
if (fCurrentFile != NULL) {
|
||||
return fCurrentFile->GetPosition();
|
||||
}
|
||||
return Position();
|
||||
}
|
||||
|
||||
const char* Scanner::GetFileName()
|
||||
{
|
||||
if (fCurrentFile != NULL) {
|
||||
return fCurrentFile->GetFileName();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Scanner::Include(const char* file)
|
||||
{
|
||||
PPDFile* newFile = new PPDFile(file, fCurrentFile);
|
||||
if (newFile->InitCheck() != B_OK) {
|
||||
delete newFile;
|
||||
return false;
|
||||
}
|
||||
|
||||
fCurrentFile = newFile;
|
||||
NextChar();
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _SCANNER_H
|
||||
#define _SCANNER_H
|
||||
|
||||
#include "CharacterClasses.h"
|
||||
#include "PPDFile.h"
|
||||
|
||||
class Scanner {
|
||||
private:
|
||||
PPDFile* fCurrentFile;
|
||||
BString fLastError;
|
||||
BString fWarnings;
|
||||
|
||||
BString* Scan(bool (cond)(int ch));
|
||||
bool ScanHexadecimalSubstring(BString* literal);
|
||||
BString* ScanLiteral(bool quotedValue, int separator);
|
||||
|
||||
public:
|
||||
Scanner(const char* file);
|
||||
virtual ~Scanner();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
// Returns the current character or -1 if on EOF.
|
||||
int GetCurrentChar();
|
||||
// Reads the next character. Use GetChar to read the current
|
||||
void NextChar();
|
||||
// Returns the position of the current character
|
||||
Position GetPosition();
|
||||
// Returns the file name of the current character
|
||||
const char* GetFileName();
|
||||
|
||||
BString* ScanIdent() { return Scan(IsIdentChar); }
|
||||
BString* ScanOption() { return Scan(IsOptionChar); }
|
||||
BString* ScanSymbolValue() { return Scan(IsPrintableWithoutWhitespaces); }
|
||||
BString* ScanInvocationValue() { return Scan(IsPrintableWithWhitespaces); }
|
||||
BString* ScanStringValue() { return Scan(IsStringChar); }
|
||||
BString* ScanTranslationValue(int separator = kEof)
|
||||
{ return ScanLiteral(false, separator); }
|
||||
BString* ScanQuotedValue() { return ScanLiteral(true, kEof); }
|
||||
|
||||
// Include the file at the current position and read the first char.
|
||||
bool Include(const char* file);
|
||||
|
||||
void Warning(const char* message);
|
||||
const char* GetWarningMessage();
|
||||
bool HasWarning();
|
||||
|
||||
void Error(const char* message);
|
||||
const char* GetErrorMessage();
|
||||
bool HasError();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _AUTO_DELETE_H
|
||||
#define _AUTO_DELETE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
Typical usage of this class:
|
||||
|
||||
AClass* Klass::Method(int arg) {
|
||||
AutoDelete<AClass> variable(new AClass());
|
||||
|
||||
if (!IsValid(arg)) {
|
||||
...
|
||||
// AutoDelete automatically deletes the AClass object.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
variable.Get()->MethodOfAClass();
|
||||
|
||||
// Use Release() to prevent deletion of AClass object.
|
||||
return variable.Release();
|
||||
}
|
||||
*/
|
||||
|
||||
template <class Tp>
|
||||
class AutoDelete {
|
||||
private:
|
||||
Tp* fObject;
|
||||
bool fOwnsObject;
|
||||
|
||||
// Deletes the object if it owns it
|
||||
void Delete()
|
||||
{
|
||||
if (fOwnsObject) {
|
||||
delete fObject; fObject = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Sets the object the class owns
|
||||
AutoDelete(Tp* object = NULL) : fObject(object), fOwnsObject(true) { }
|
||||
|
||||
// Deletes the object if it owns it
|
||||
virtual ~AutoDelete()
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
|
||||
// Sets the object the class owns.
|
||||
// Deletes a previously owned object and
|
||||
// sets the owning flag for the new object.
|
||||
void Set(Tp* object)
|
||||
{
|
||||
if (fObject == object) return;
|
||||
|
||||
Delete();
|
||||
fOwnsObject = true;
|
||||
fObject = object;
|
||||
}
|
||||
|
||||
// Returns the object
|
||||
Tp* Get()
|
||||
{
|
||||
return fObject;
|
||||
}
|
||||
|
||||
// Returns the object and sets owning to false
|
||||
// The Get method can still be used to retrieve the object.
|
||||
Tp* Release()
|
||||
{
|
||||
fOwnsObject = false;
|
||||
return fObject;
|
||||
}
|
||||
|
||||
// Sets the owning flag
|
||||
void SetOwnsObject(bool ownsObject)
|
||||
{
|
||||
fOwnsObject = ownsObject;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
SubDir HAIKU_TOP src tests add-ons print ppd test ;
|
||||
|
||||
# SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src tests add-ons print ppd model ;
|
||||
SubDirHdrs $(HAIKU_TOP) src tests add-ons print ppd parser ;
|
||||
SubDirHdrs $(HAIKU_TOP) src tests add-ons print ppd ui ;
|
||||
|
||||
# TODO convert .rsrc to .rdef
|
||||
# AddResources PPDConfig : PPDConfigApplication.rsrc ;
|
||||
|
||||
SimpleTest PPDConfig :
|
||||
PPDConfigApplication.cpp
|
||||
: be root libppdtest.a
|
||||
;
|
||||
|
||||
SimpleTest PPDTest :
|
||||
Test.cpp
|
||||
TestParser.cpp
|
||||
TestScanner.cpp
|
||||
:
|
||||
be root libppdtest.a
|
||||
;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef MSG_CONSTS_H
|
||||
#define MSG_CONSTS_H
|
||||
|
||||
#define MENU_APP_NEW 'APnw'
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "PPDConfigApplication.h"
|
||||
#include "PrinterSelection.h"
|
||||
|
||||
AppWindow::AppWindow(BRect aRect)
|
||||
: BWindow(aRect, APPLICATION, B_TITLED_WINDOW, 0) {
|
||||
// add menu bar
|
||||
BRect rect = BRect(0, 0, aRect.Width(), aRect.Height());
|
||||
fMenuBar = new BMenuBar(rect, "menu_bar");
|
||||
BMenu *menu;
|
||||
|
||||
menu = new BMenu("File");
|
||||
menu->AddItem(new BMenuItem("About ...", new BMessage(B_ABOUT_REQUESTED), 'A'));
|
||||
menu->AddSeparatorItem();
|
||||
menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
|
||||
fMenuBar->AddItem(menu);
|
||||
|
||||
AddChild(fMenuBar);
|
||||
|
||||
float x = aRect.Width() / 2 - 3;
|
||||
float right = rect.right - 3;
|
||||
|
||||
// add view
|
||||
aRect.Set(0, fMenuBar->Bounds().Height()+1, x, aRect.Height());
|
||||
PrinterSelectionView* printerSelection = new PrinterSelectionView(aRect,
|
||||
"printer-selection",
|
||||
B_FOLLOW_TOP_BOTTOM,
|
||||
B_WILL_DRAW);
|
||||
AddChild(printerSelection);
|
||||
printerSelection->SetMessage(new BMessage('prnt'));
|
||||
printerSelection->SetTarget(this);
|
||||
|
||||
aRect.left = x + 3;
|
||||
aRect.right = right;
|
||||
AddChild(fConfig = new PPDConfigView(aRect, "ppd-config",
|
||||
B_FOLLOW_ALL_SIDES,
|
||||
B_WILL_DRAW));
|
||||
|
||||
// make window visible
|
||||
Show();
|
||||
}
|
||||
|
||||
void AppWindow::MessageReceived(BMessage *message) {
|
||||
const char* file;
|
||||
switch(message->what) {
|
||||
case MENU_APP_NEW:
|
||||
break;
|
||||
case B_ABOUT_REQUESTED:
|
||||
AboutRequested();
|
||||
break;
|
||||
case 'prnt':
|
||||
if (message->FindString("file", &file) == B_OK) {
|
||||
BMessage settings;
|
||||
fConfig->Set(file, settings);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AppWindow::QuitRequested() {
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
return(true);
|
||||
}
|
||||
|
||||
void AppWindow::AboutRequested() {
|
||||
BAlert *about = new BAlert(APPLICATION,
|
||||
APPLICATION " " VERSION "\nPrototype for PPD printer selection and configuration.\n\n"
|
||||
"Written 2008.\n\n"
|
||||
"By Michael Pfeiffer.\n\n"
|
||||
"EMail: [email protected].","Close");
|
||||
about->Go();
|
||||
}
|
||||
|
||||
PPDConfigApplication::PPDConfigApplication() : BApplication(SIGNATURE) {
|
||||
BRect aRect;
|
||||
// set up a rectangle and instantiate a new window
|
||||
aRect.Set(100, 80, 950, 580);
|
||||
window = NULL;
|
||||
window = new AppWindow(aRect);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
PPDConfigApplication app;
|
||||
app.Run();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _PPD_CONFIG_H
|
||||
#define _PPD_CONFIG_H
|
||||
|
||||
#include <AppKit.h>
|
||||
#include <InterfaceKit.h>
|
||||
#include "PPDConfigView.h"
|
||||
#include "MsgConsts.h"
|
||||
|
||||
#define APPLICATION "PPD Printer Selection and Configuration Prototype"
|
||||
#define SIGNATURE "application/x-vnd.mwp-ppd-prototype"
|
||||
#define VERSION "1.0"
|
||||
|
||||
class AppWindow : public BWindow {
|
||||
public:
|
||||
AppWindow(BRect);
|
||||
bool QuitRequested();
|
||||
void AboutRequested();
|
||||
void MessageReceived(BMessage *message);
|
||||
|
||||
private:
|
||||
BMenuBar *fMenuBar;
|
||||
PPDConfigView *fConfig;
|
||||
};
|
||||
|
||||
class PPDConfigApplication : public BApplication {
|
||||
public:
|
||||
AppWindow *window;
|
||||
PPDConfigApplication();
|
||||
};
|
||||
|
||||
#define my_app ((PPDConfigApplication*)be_app)
|
||||
|
||||
#endif
|
||||
Binary file not shown.
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <List.h>
|
||||
|
||||
void TestScanner();
|
||||
void TestParser();
|
||||
void TestPPDParser(bool all, bool verbose = true);
|
||||
void TestExtractUI();
|
||||
|
||||
const char* gPPDFile = "aptollw1.ppd";
|
||||
|
||||
static BList gArgs;
|
||||
|
||||
bool enabled(const char* name, const char* arg)
|
||||
{
|
||||
gArgs.AddItem((void*)name);
|
||||
if (arg == NULL) return false;
|
||||
if (strcmp(arg, "all") == 0) return true;
|
||||
return strcmp(arg, name) == 0;
|
||||
}
|
||||
|
||||
void printArgs(const char* programName)
|
||||
{
|
||||
fprintf(stderr, "%s: argument\n", programName);
|
||||
fprintf(stderr, "Argument is missing. The available arguments are:\n");
|
||||
fprintf(stderr, " all\n");
|
||||
for (int i = 0; i < gArgs.CountItems(); i ++) {
|
||||
fprintf(stderr, " %s\n", (const char*)gArgs.ItemAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const char* arg = argc >= 2 ? argv[1] : NULL;
|
||||
|
||||
if (argc >= 3) {
|
||||
gPPDFile = argv[2];
|
||||
}
|
||||
|
||||
if (enabled("scanner", arg)) {
|
||||
TestScanner();
|
||||
}
|
||||
if (enabled("parser", arg)) {
|
||||
TestParser();
|
||||
}
|
||||
if (enabled("ppd", arg)) {
|
||||
TestPPDParser(true);
|
||||
}
|
||||
if (enabled("header", arg)) {
|
||||
TestPPDParser(false);
|
||||
}
|
||||
if (enabled("ui", arg)) {
|
||||
TestExtractUI();
|
||||
}
|
||||
if (enabled("ppd-timing", arg)) {
|
||||
TestPPDParser(true, false);
|
||||
}
|
||||
if (enabled("header-timing", arg)) {
|
||||
TestPPDParser(false, false);
|
||||
}
|
||||
|
||||
if (arg == NULL) {
|
||||
printArgs(argv[0]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _TEST_H
|
||||
#define _TEST_H
|
||||
|
||||
extern const char* gPPDFile;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "Parser.h"
|
||||
#include "Test.h"
|
||||
|
||||
#include <StopWatch.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void TestParser()
|
||||
{
|
||||
Parser parser(gPPDFile);
|
||||
if (parser.InitCheck() != B_OK) {
|
||||
fprintf(stderr, "Could not open ppd file %s\n", gPPDFile);
|
||||
return;
|
||||
}
|
||||
|
||||
Statement* statement;
|
||||
do {
|
||||
statement = parser.Parse();
|
||||
if (statement != NULL) {
|
||||
statement->Print();
|
||||
}
|
||||
delete statement;
|
||||
} while (statement != NULL);
|
||||
}
|
||||
|
||||
#include "PPDParser.h"
|
||||
|
||||
static PPD* OpenTestFile(bool all, bool timing)
|
||||
{
|
||||
BStopWatch* stopWatch = NULL;
|
||||
if (timing) {
|
||||
stopWatch = new BStopWatch("PPDParser");
|
||||
}
|
||||
PPDParser parser(gPPDFile);
|
||||
|
||||
if (parser.InitCheck() != B_OK) {
|
||||
fprintf(stderr, "Could not open ppd file %s\n", gPPDFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PPD* ppd = all ? parser.ParseAll() : parser.ParseHeader();
|
||||
|
||||
delete stopWatch;
|
||||
|
||||
if (ppd == NULL) {
|
||||
fprintf(stderr, "Parser returned NULL\n");
|
||||
fprintf(stderr, "%s\n", parser.GetErrorMessage());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ppd;
|
||||
}
|
||||
|
||||
void TestPPDParser(bool all, bool verbose)
|
||||
{
|
||||
PPD* ppd = OpenTestFile(all, !verbose);
|
||||
if (ppd == NULL) return;
|
||||
if (verbose) {
|
||||
ppd->Print();
|
||||
}
|
||||
delete ppd;
|
||||
}
|
||||
|
||||
void ExtractChildren(StatementList* list, int level);
|
||||
|
||||
void Indent(int level)
|
||||
{
|
||||
for (; level > 0; level --) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
void PrintValue(const char* label, Value* arg, int level)
|
||||
{
|
||||
Indent(level);
|
||||
|
||||
if (label != NULL) {
|
||||
printf("%s ", label);
|
||||
}
|
||||
|
||||
if (arg != NULL) {
|
||||
BString* value = arg->GetValue();
|
||||
BString* translation = arg->GetTranslation();
|
||||
if (translation != NULL) {
|
||||
printf("%s", translation->String());
|
||||
}
|
||||
if (value != NULL) {
|
||||
printf(" [%s]", value->String());
|
||||
}
|
||||
} else {
|
||||
printf("NULL");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
bool ExtractGroup(Statement* statement, int level)
|
||||
{
|
||||
GroupStatement group(statement);
|
||||
if (group.IsOpenGroup()) {
|
||||
const char* translation = group.GetGroupTranslation();
|
||||
Indent(level);
|
||||
if (translation != NULL) {
|
||||
printf("%s", translation);
|
||||
}
|
||||
const char* name = group.GetGroupName();
|
||||
if (name != NULL) {
|
||||
printf("[%s]", name);
|
||||
}
|
||||
printf("\n");
|
||||
ExtractChildren(statement->GetChildren(), level+1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ExtractChildren(StatementList* list, int level)
|
||||
{
|
||||
if (list == NULL) return;
|
||||
for (int32 i = 0; i < list->Size(); i ++) {
|
||||
Statement* statement = list->StatementAt(i);
|
||||
if (!ExtractGroup(statement, level)) {
|
||||
if (statement->GetType() == Statement::kValue) {
|
||||
PrintValue(NULL, statement->GetOption(), level);
|
||||
} else if (statement->GetType() == Statement::kDefault) {
|
||||
PrintValue("Default", statement->GetValue(), level);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestExtractUI()
|
||||
{
|
||||
PPD* ppd = OpenTestFile(true, false);
|
||||
if (ppd == NULL) return;
|
||||
|
||||
for (int32 i = 0; i < ppd->Size(); i++) {
|
||||
Statement* statement = ppd->StatementAt(i);
|
||||
ExtractGroup(statement, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "CharacterClasses.h"
|
||||
#include "Scanner.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void Print(Scanner* scanner)
|
||||
{
|
||||
Position position = scanner->GetPosition();
|
||||
const char* filename = scanner->GetFileName();
|
||||
int ch = scanner->GetCurrentChar();
|
||||
printf("[%d, %d] (%s) %c\n", position.x, position.y, filename, ch);
|
||||
}
|
||||
|
||||
void TestScanner()
|
||||
{
|
||||
Scanner scanner("main.ppd");
|
||||
if (scanner.InitCheck() != B_OK) {
|
||||
fprintf(stderr, "Could not open file main.ppd\n");
|
||||
return;
|
||||
}
|
||||
|
||||
scanner.NextChar();
|
||||
for (int i = 0; i < 10; i ++) {
|
||||
int ch = scanner.GetCurrentChar();
|
||||
if (ch == kEof) {
|
||||
fprintf(stderr, "Unexpected end of file!\n");
|
||||
return;
|
||||
}
|
||||
Print(&scanner);
|
||||
scanner.NextChar();
|
||||
}
|
||||
|
||||
if (!scanner.Include("include.ppd")) {
|
||||
fprintf(stderr, "Could not include file include.ppd\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (scanner.GetCurrentChar() != kEof) {
|
||||
Print(&scanner);
|
||||
scanner.NextChar();
|
||||
}
|
||||
|
||||
BString string;
|
||||
string.Append('a', 1);
|
||||
printf("%d\n", (int)string.Length());
|
||||
string.Append((char)0, 1);
|
||||
string.Append('b', 1);
|
||||
printf("%d\n", (int)string.Length());
|
||||
for (int i = 0; i < string.Length(); i ++) {
|
||||
printf("%c ", string.String()[i]);
|
||||
}
|
||||
|
||||
printf("%d\n", '"');
|
||||
}
|
||||
@@ -0,0 +1,656 @@
|
||||
*PPD-Adobe: "4.1"
|
||||
*% Adobe Systems PostScript(R) Printer Description File
|
||||
*% Copyright 1987-1994 Adobe Systems Incorporated.
|
||||
*% All Rights Reserved.
|
||||
*% Permission is granted for redistribution of this file as
|
||||
*% long as this copyright notice is intact and the contents
|
||||
*% of the file is not altered in any way from its original form.
|
||||
*% End of Copyright statement
|
||||
*FormatVersion: "4.1"
|
||||
*FileVersion: "1.15"
|
||||
*LanguageEncoding: ISOLatin1
|
||||
*LanguageVersion: English
|
||||
*PCFileName: "APTOLLW1.PPD"
|
||||
*Product: "(LaserWriter Pro 630)"
|
||||
*PSVersion: "(2010.130) 1"
|
||||
*ModelName: "Apple LaserWriter Pro 630"
|
||||
*ShortNickName: "Apple LaserWriter Pro 630"
|
||||
*NickName: "Apple LaserWriter Pro 630 v2010.130"
|
||||
|
||||
*% === Options and Constraints =========
|
||||
*OpenGroup: InstallableOptions/Options Installed
|
||||
*OpenUI *Option1/Memory Configuration: PickOne
|
||||
*DefaultOption1: None
|
||||
*Option1 None/Standard 8 MB RAM: ""
|
||||
*Option1 16Meg/16 MB Upgrade: ""
|
||||
*Option1 32Meg/32 MB Upgrade: ""
|
||||
*?Option1: "
|
||||
(None)currentsystemparams/RamSize get
|
||||
dup 16777216 eq{pop pop(16Meg)}{33554432 eq{pop(32Meg)}if}ifelse
|
||||
=
|
||||
"
|
||||
*End
|
||||
*CloseUI: *Option1
|
||||
|
||||
*OpenUI *Option2/Cassette (500 Sheets): PickOne
|
||||
*DefaultOption2: False
|
||||
*Option2 True/Installed: ""
|
||||
*Option2 False/Not Installed: ""
|
||||
*Option2 Preferred/Installed and Preferred: "
|
||||
1 dict dup /InputAttributes 1 dict dup /Priority [2 0 1 3] put put setpagedevice"
|
||||
*End
|
||||
*?Option2: "
|
||||
save
|
||||
currentpagedevice
|
||||
/InputAttributes get
|
||||
2 known {(True)}{(False)} ifelse = flush
|
||||
restore "
|
||||
*End
|
||||
*CloseUI: *Option2
|
||||
|
||||
*OpenUI *Option3/Envelope Feeder: Boolean
|
||||
*DefaultOption3: False
|
||||
*Option3 True/Installed: ""
|
||||
*Option3 False/Not Installed: ""
|
||||
*?Option3: "
|
||||
save
|
||||
currentpagedevice
|
||||
/InputAttributes get
|
||||
3 known {(True)}{(False)} ifelse = flush
|
||||
restore "
|
||||
*End
|
||||
*CloseUI: *Option3
|
||||
*CloseGroup: InstallableOptions
|
||||
|
||||
*UIConstraints: *Resolution 600dpi *Smoothing True
|
||||
*UIConstraints: *Resolution 600dpi *BitsPerPixel 4
|
||||
*UIConstraints: *Option2 False *InputSlot Lower
|
||||
*UIConstraints: *Option3 False *InputSlot Envelope
|
||||
|
||||
*UIConstraints: *PageSize Letter *InputSlot Envelope
|
||||
*UIConstraints: *PageSize Legal *InputSlot Envelope
|
||||
*UIConstraints: *PageSize A4 *InputSlot Envelope
|
||||
*UIConstraints: *PageSize B5 *InputSlot Envelope
|
||||
*UIConstraints: *PageSize LetterSmall *InputSlot Envelope
|
||||
*UIConstraints: *PageSize A4Small *InputSlot Envelope
|
||||
*UIConstraints: *PageSize LegalSmall *InputSlot Envelope
|
||||
*UIConstraints: *InputSlot Envelope *PageSize Letter
|
||||
*UIConstraints: *InputSlot Envelope *PageSize Legal
|
||||
*UIConstraints: *InputSlot Envelope *PageSize A4
|
||||
*UIConstraints: *InputSlot Envelope *PageSize B5
|
||||
*UIConstraints: *InputSlot Envelope *PageSize LetterSmall
|
||||
*UIConstraints: *InputSlot Envelope *PageSize A4Small
|
||||
*UIConstraints: *InputSlot Envelope *PageSize LegalSmall
|
||||
*UIConstraints: *PageRegion Letter *InputSlot Envelope
|
||||
*UIConstraints: *PageRegion Legal *InputSlot Envelope
|
||||
*UIConstraints: *PageRegion A4 *InputSlot Envelope
|
||||
*UIConstraints: *PageRegion B5 *InputSlot Envelope
|
||||
*UIConstraints: *PageRegion LetterSmall *InputSlot Envelope
|
||||
*UIConstraints: *PageRegion A4Small *InputSlot Envelope
|
||||
*UIConstraints: *PageRegion LegalSmall *InputSlot Envelope
|
||||
*UIConstraints: *InputSlot Envelope *PageRegion Letter
|
||||
*UIConstraints: *InputSlot Envelope *PageRegion Legal
|
||||
*UIConstraints: *InputSlot Envelope *PageRegion A4
|
||||
*UIConstraints: *InputSlot Envelope *PageRegion B5
|
||||
*UIConstraints: *InputSlot Envelope *PageRegion LetterSmall
|
||||
*UIConstraints: *InputSlot Envelope *PageRegion A4Small
|
||||
*UIConstraints: *InputSlot Envelope *PageRegion LegalSmall
|
||||
|
||||
*UIConstraints: *Option1 None *VMOption
|
||||
|
||||
*UIConstraints: *Option1 16Meg *VMOption None
|
||||
*UIConstraints: *Option1 16Meg *VMOption 32Meg
|
||||
|
||||
*UIConstraints: *Option1 32Meg *VMOption None
|
||||
*UIConstraints: *Option1 32Meg *VMOption 16Meg
|
||||
|
||||
*% ==== Device Capabilities ===============
|
||||
*LanguageLevel: "2"
|
||||
*Protocols: BCP
|
||||
*Emulators: hpcl
|
||||
*StartEmulator_hpcl: "currentfile /hpcl statusdict /emulate get exec "
|
||||
*StopEmulator_hpcl: "<1B7F>0"
|
||||
|
||||
*FreeVM: "2406169"
|
||||
*VMOption None/Standard 8 MB RAM: "2406169"
|
||||
*VMOption 16Meg/16 MB Upgrade: "10851725"
|
||||
*VMOption 32Meg/32 MB Upgrade: "27598075"
|
||||
*ColorDevice: False
|
||||
*DefaultColorSpace: Gray
|
||||
*VariablePaperSize: False
|
||||
*FileSystem: True
|
||||
*?FileSystem: "
|
||||
save false
|
||||
(%disk?%)
|
||||
{ currentdevparams dup /Writeable known
|
||||
{ /Writeable get {pop true} if } { pop } ifelse
|
||||
} 10 string /IODevice resourceforall
|
||||
{(True)}{(False)} ifelse = flush
|
||||
restore"
|
||||
*End
|
||||
|
||||
*Throughput: "8"
|
||||
*Password: "()"
|
||||
*ExitServer: "
|
||||
count 0 eq
|
||||
{ false } { true exch startjob } ifelse
|
||||
not {
|
||||
(WARNING: Cannot modify initial VM.) =
|
||||
(Missing or invalid password.) =
|
||||
(Please contact the author of this software.) = flush quit
|
||||
} if
|
||||
"
|
||||
*End
|
||||
*Reset: "
|
||||
count 0 eq
|
||||
{ false } { true exch startjob } ifelse
|
||||
not {
|
||||
(WARNING: Cannot reset printer.) =
|
||||
(Missing or invalid password.) =
|
||||
(Please contact the author of this software.) = flush quit
|
||||
} if
|
||||
systemdict /quit get exec
|
||||
(WARNING : Printer Reset Failed.) = flush
|
||||
"
|
||||
*End
|
||||
|
||||
*OpenUI *Resolution/Choose Resolution: PickOne
|
||||
*OrderDependency: 10 AnySetup *Resolution
|
||||
*DefaultResolution: 600dpi
|
||||
*Resolution 600dpi: "1 dict dup /HWResolution [600 600] put setpagedevice"
|
||||
*Resolution 300dpi: "1 dict dup /HWResolution [300 300] put setpagedevice"
|
||||
*?Resolution: "
|
||||
save
|
||||
/ActualValues /ProcSet findresource
|
||||
begin HWResolution end
|
||||
0 get
|
||||
( ) cvs print
|
||||
(dpi)
|
||||
= flush
|
||||
restore
|
||||
"
|
||||
*End
|
||||
*CloseUI: *Resolution
|
||||
|
||||
*% Halftone Information ===============
|
||||
*ScreenFreq: "85.0"
|
||||
*ScreenAngle: "45.0"
|
||||
*DefaultScreenProc: Dot
|
||||
*ScreenProc Dot: "
|
||||
{abs exch abs 2 copy add 1 gt {1 sub dup mul exch
|
||||
1 sub dup mul add 1 sub } {dup mul exch dup mul
|
||||
add 1 exch sub } ifelse }
|
||||
"
|
||||
*End
|
||||
*ScreenProc Line: "{ pop }"
|
||||
*ScreenProc Ellipse: "{ dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub }"
|
||||
|
||||
*DefaultTransfer: Null
|
||||
*Transfer Null: "{ }"
|
||||
*Transfer Null.Inverse: "{ 1 exch sub }"
|
||||
|
||||
*OpenUI *Smoothing/FinePrint(TM): Boolean
|
||||
*OrderDependency: 50 AnySetup *Smoothing
|
||||
*DefaultSmoothing: False
|
||||
*Smoothing True/On: "
|
||||
2 dict
|
||||
dup /PostRenderingEnhance true put
|
||||
dup /PostRenderingEnhanceDetails
|
||||
2 dict
|
||||
dup /Type 1 put
|
||||
dup /ActualPostRenderingEnhance true put
|
||||
put
|
||||
setpagedevice
|
||||
"
|
||||
*End
|
||||
*Smoothing False/Off: "
|
||||
2 dict
|
||||
dup /PostRenderingEnhance false put
|
||||
dup /PostRenderingEnhanceDetails
|
||||
2 dict
|
||||
dup /Type 1 put
|
||||
dup /ActualPostRenderingEnhance false put
|
||||
put
|
||||
setpagedevice
|
||||
"
|
||||
*End
|
||||
*?Smoothing: "
|
||||
save currentpagedevice /PostRenderingEnhanceDetails get
|
||||
/ActualPostRenderingEnhance get
|
||||
{(True)}{(False)} ifelse = flush restore"
|
||||
*End
|
||||
*CloseUI: *Smoothing
|
||||
|
||||
*OpenUI *BitsPerPixel/PhotoGrade(TM): Boolean
|
||||
*OrderDependency: 50 AnySetup *BitsPerPixel
|
||||
*DefaultBitsPerPixel: None
|
||||
*BitsPerPixel 4/On: "
|
||||
2 dict
|
||||
dup /PreRenderingEnhance true put
|
||||
dup /PreRenderingEnhanceDetails
|
||||
2 dict
|
||||
dup /Type 1 put
|
||||
dup /ActualPreRenderingEnhance true put
|
||||
put
|
||||
setpagedevice
|
||||
"
|
||||
*End
|
||||
*BitsPerPixel None/Off: "
|
||||
2 dict
|
||||
dup /PreRenderingEnhance false put
|
||||
dup /PreRenderingEnhanceDetails
|
||||
2 dict
|
||||
dup /Type 1 put
|
||||
dup /ActualPreRenderingEnhance false put
|
||||
put
|
||||
setpagedevice
|
||||
"
|
||||
*End
|
||||
*?BitsPerPixel: "
|
||||
save currentpagedevice /PreRenderingEnhanceDetails get
|
||||
/ActualPreRenderingEnhance get
|
||||
{(4)}{(None)} ifelse = flush restore"
|
||||
*End
|
||||
*CloseUI: *BitsPerPixel
|
||||
|
||||
*% Paper Handling ===================
|
||||
|
||||
*% Code in this section both selects a tray and sets up a frame buffer.
|
||||
*OpenUI *PageSize: PickOne
|
||||
*OrderDependency: 30 AnySetup *PageSize
|
||||
*DefaultPageSize: Letter
|
||||
*PageSize Letter/US Letter: "
|
||||
2 dict dup /PageSize [612 792] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageSize Legal/US Legal: "
|
||||
2 dict dup /PageSize [612 1008] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageSize A4: "
|
||||
2 dict dup /PageSize [595 842] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageSize B5: "
|
||||
2 dict dup /PageSize [516 729] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageSize LetterSmall/US Letter Small: "
|
||||
2 dict dup /PageSize [612 792] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageSize A4Small/A4 Small: "
|
||||
2 dict dup /PageSize [595 842] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageSize LegalSmall/US Legal Small: "
|
||||
2 dict dup /PageSize [612 1008] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageSize Monarch/Monarch Envelope Edge Fed: "
|
||||
2 dict dup /PageSize [611 792] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageSize Com10/Com10 Envelope Edge Fed: "
|
||||
2 dict dup /PageSize [610 792] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*?PageSize: "
|
||||
save
|
||||
currentpagedevice /PageSize get aload pop
|
||||
2 copy gt {exch} if
|
||||
(Unknown)
|
||||
7 dict
|
||||
dup [612 792] (Letter) put
|
||||
dup [612 1008] (Legal) put
|
||||
dup [595 842] (A4) put
|
||||
dup [516 729] (B5) put
|
||||
dup [610 792] (Comm10) put
|
||||
dup [611 792] (Monarch) put
|
||||
{ exch aload pop 4 index sub abs 5 le exch
|
||||
5 index sub abs 5 le and
|
||||
{exch pop exit} {pop} ifelse
|
||||
} bind forall
|
||||
= flush pop pop
|
||||
restore
|
||||
"
|
||||
*End
|
||||
*CloseUI: *PageSize
|
||||
|
||||
*OpenUI *PageRegion: PickOne
|
||||
*OrderDependency: 40 AnySetup *PageRegion
|
||||
*DefaultPageRegion: Letter
|
||||
*PageRegion Letter/US Letter: "
|
||||
2 dict dup /PageSize [612 792] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageRegion Legal/US Legal: "
|
||||
2 dict dup /PageSize [612 1008] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageRegion A4: "
|
||||
2 dict dup /PageSize [595 842] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageRegion B5: "
|
||||
2 dict dup /PageSize [516 729] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageRegion LetterSmall/US Letter Small: "
|
||||
2 dict dup /PageSize [612 792] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageRegion A4Small/A4 Small: "
|
||||
2 dict dup /PageSize [595 842] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageRegion LegalSmall/US Legal Small: "
|
||||
2 dict dup /PageSize [612 1008] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageRegion Monarch/Monarch Envelope Edge Fed: "
|
||||
2 dict dup /PageSize [611 792] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*PageRegion Com10/Com10 Envelope Edge Fed: "
|
||||
2 dict dup /PageSize [610 792] put dup /ImagingBBox null put setpagedevice"
|
||||
*End
|
||||
*CloseUI: *PageRegion
|
||||
|
||||
*% The following entries provide information about specific paper keywords.
|
||||
*DefaultImageableArea: Letter
|
||||
*ImageableArea Letter/US Letter: "9.84 14.2201 601.2 783.66 "
|
||||
*ImageableArea Legal/US Legal: "9.84 14.2201 601.2 999.66 "
|
||||
*ImageableArea A4: "9.84 14.2201 578.16 833.82 "
|
||||
*ImageableArea B5: "9.84 14.22 501.36 720.78 "
|
||||
*ImageableArea LetterSmall/US Letter Small: "31 31 583 761 "
|
||||
*ImageableArea A4Small/A4 Small: "29 31 567 812 "
|
||||
*ImageableArea LegalSmall/US Legal Small: "64 54 548 954 "
|
||||
*ImageableArea Monarch/Monarch Envelope Edge Fed: "9.84 257 274 783.66 "
|
||||
*ImageableArea Com10/Com10 Envelope Edge Fed: "9.84 113 292 783.66 "
|
||||
*?ImageableArea: "
|
||||
save
|
||||
/cvp { ( ) cvs print ( ) print } bind def
|
||||
/upperright {10000 mul floor 10000 div} bind def
|
||||
/lowerleft {10000 mul ceiling 10000 div} bind def
|
||||
newpath clippath pathbbox
|
||||
4 -2 roll exch 2 {lowerleft cvp} repeat
|
||||
exch 2 {upperright cvp} repeat flush
|
||||
restore
|
||||
"
|
||||
*End
|
||||
|
||||
*% These provide the physical dimensions of the paper (by keyword)
|
||||
*DefaultPaperDimension: Letter
|
||||
*PaperDimension Letter/US Letter: "612 792"
|
||||
*PaperDimension Legal/US Legal: "612 1008"
|
||||
*PaperDimension A4: "595 842"
|
||||
*PaperDimension B5: "516 729"
|
||||
*PaperDimension LetterSmall/US Letter Small: "612 792"
|
||||
*PaperDimension A4Small/A4 Small: "595 842"
|
||||
*PaperDimension LegalSmall/US Legal Small: "612 1008"
|
||||
*PaperDimension Monarch/Monarch Envelope Edge Fed: "611 792"
|
||||
*PaperDimension Com10/Com10 Envelope Edge Fed: "610 792"
|
||||
|
||||
*RequiresPageRegion Multipurpose: True
|
||||
|
||||
*OpenUI *InputSlot: PickOne
|
||||
*OrderDependency: 20 AnySetup *InputSlot
|
||||
*DefaultInputSlot: Upper
|
||||
*InputSlot Upper/Cassette (250 Sheets): "
|
||||
currentpagedevice /InputAttributes get 0 get
|
||||
dup null eq
|
||||
{ pop }
|
||||
{ dup length 1 add dict copy
|
||||
dup /InputAttributes
|
||||
1 dict dup /Priority [0] put
|
||||
put setpagedevice
|
||||
} ifelse"
|
||||
*End
|
||||
*InputSlot Multipurpose/Multipurpose Tray: "
|
||||
1 dict dup /ManualFeed true put setpagedevice"
|
||||
*End
|
||||
*InputSlot Lower/Cassette (500 Sheets): "
|
||||
currentpagedevice /InputAttributes get 2 get
|
||||
dup null eq
|
||||
{ pop }
|
||||
{ dup length 1 add dict copy
|
||||
dup /InputAttributes
|
||||
1 dict dup /Priority [2 0] put
|
||||
put setpagedevice
|
||||
} ifelse"
|
||||
*End
|
||||
*InputSlot Envelope/Envelope Feeder: "
|
||||
currentpagedevice /InputAttributes get 3 get
|
||||
dup null eq
|
||||
{ pop }
|
||||
{ dup length 1 add dict copy
|
||||
dup /InputAttributes
|
||||
1 dict dup /Priority [3 0] put
|
||||
put setpagedevice
|
||||
} ifelse"
|
||||
*End
|
||||
*?InputSlot: "
|
||||
save
|
||||
3 dict
|
||||
dup /0 (Upper) put
|
||||
dup /1 (Multipurpose) put
|
||||
dup /2 (Lower) put
|
||||
dup /3 (Envelope) put
|
||||
currentpagedevice /InputAttributes get
|
||||
dup /Priority known
|
||||
{ /Priority get 0 get ( ) cvs cvn get }
|
||||
{
|
||||
dup length 1 eq
|
||||
{ {pop} forall ( ) cvs cvn get }
|
||||
{ pop pop (Unknown) } ifelse
|
||||
} ifelse
|
||||
= flush
|
||||
restore
|
||||
"
|
||||
*End
|
||||
*CloseUI: *InputSlot
|
||||
|
||||
*DefaultOutputBin: OnlyOne
|
||||
*DefaultOutputOrder: Normal
|
||||
|
||||
*OpenUI *ManualFeed/Manual Feed: Boolean
|
||||
*OrderDependency: 20 AnySetup *ManualFeed
|
||||
*DefaultManualFeed: False
|
||||
*ManualFeed True: "1 dict dup /ManualFeed true put setpagedevice"
|
||||
*ManualFeed False: "1 dict dup /ManualFeed false put setpagedevice"
|
||||
*?ManualFeed: "
|
||||
save
|
||||
currentpagedevice /ManualFeed get
|
||||
{(True)}{(False)}ifelse = flush
|
||||
restore
|
||||
"
|
||||
*End
|
||||
*CloseUI: *ManualFeed
|
||||
|
||||
*OpenUI *TraySwitch: Boolean
|
||||
*OrderDependency: 50 AnySetup *TraySwitch
|
||||
*DefaultTraySwitch: False
|
||||
*TraySwitch True: "1 dict dup /TraySwitch true put setpagedevice"
|
||||
*TraySwitch False: "1 dict dup /TraySwitch false put setpagedevice"
|
||||
*?TraySwitch: "
|
||||
save
|
||||
currentpagedevice /TraySwitch get
|
||||
{(True)}{(False)}ifelse = flush
|
||||
restore
|
||||
"
|
||||
*End
|
||||
*CloseUI: *TraySwitch
|
||||
|
||||
*% Font Information =====================
|
||||
*DefaultFont: Courier
|
||||
*Font AvantGarde-Book: Standard "(001.002)" Standard ROM
|
||||
*Font AvantGarde-BookOblique: Standard "(001.002)" Standard ROM
|
||||
*Font AvantGarde-Demi: Standard "(001.003)" Standard ROM
|
||||
*Font AvantGarde-DemiOblique: Standard "(001.003)" Standard ROM
|
||||
*Font Bookman-Demi: Standard "(001.003S)" Standard ROM
|
||||
*Font Bookman-DemiItalic: Standard "(001.003S)" Standard ROM
|
||||
*Font Bookman-Light: Standard "(001.003S)" Standard ROM
|
||||
*Font Bookman-LightItalic: Standard "(001.003S)" Standard ROM
|
||||
*Font Courier: Standard "(002.003)" Standard ROM
|
||||
*Font Courier-Bold: Standard "(002.003)" Standard ROM
|
||||
*Font Courier-BoldOblique: Standard "(002.003)" Standard ROM
|
||||
*Font Courier-Oblique: Standard "(002.003)" Standard ROM
|
||||
*Font Helvetica: Standard "(001.006S)" Standard ROM
|
||||
*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
|
||||
*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
|
||||
*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
|
||||
*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
|
||||
*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
|
||||
*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
|
||||
*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
|
||||
*Font NewCenturySchlbk-Bold: Standard "(001.008S)" Standard ROM
|
||||
*Font NewCenturySchlbk-BoldItalic: Standard "(001.006S)" Standard ROM
|
||||
*Font NewCenturySchlbk-Italic: Standard "(001.005S)" Standard ROM
|
||||
*Font NewCenturySchlbk-Roman: Standard "(001.006S)" Standard ROM
|
||||
*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
|
||||
*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
|
||||
*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
|
||||
*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
|
||||
*Font Symbol: Special "(001.007S)" Special ROM
|
||||
*Font Times-Bold: Standard "(001.007S)" Standard ROM
|
||||
*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
|
||||
*Font Times-Italic: Standard "(001.007S)" Standard ROM
|
||||
*Font Times-Roman: Standard "(001.007S)" Standard ROM
|
||||
*Font ZapfChancery-MediumItalic: Standard "(001.006)" Standard ROM
|
||||
*Font ZapfDingbats: Special "(001.004S)" Special ROM
|
||||
|
||||
*?FontQuery: "
|
||||
save
|
||||
{ count 1 gt
|
||||
{ exch dup 127 string cvs (/) print print (:) print
|
||||
/Font resourcestatus {pop pop (Yes)} {(No)} ifelse =
|
||||
} { exit } ifelse
|
||||
} bind loop
|
||||
(*) = flush
|
||||
restore
|
||||
"
|
||||
*End
|
||||
|
||||
*?FontList: "
|
||||
save
|
||||
(*) {cvn ==} 128 string /Font resourceforall
|
||||
(*) = flush
|
||||
restore
|
||||
"
|
||||
*End
|
||||
|
||||
*% Printer Messages (verbatim from printer):
|
||||
*Message: "%%[ exitserver: permanent state may be changed ]%%"
|
||||
*Message: "%%[ Flushing: rest of job (to end-of-file) will be ignored ]%%"
|
||||
*Message: "\FontName\ not found, using Courier"
|
||||
|
||||
*% Status (format: %%[ status: <one of these> ] %%)
|
||||
*Status: "initializing"
|
||||
*Status: "idle"
|
||||
*Status: "holding"
|
||||
*Status: "busy"
|
||||
*Status: "waiting"
|
||||
*Status: "PrinterError: cover open"
|
||||
*Status: "PrinterError: warming up"
|
||||
*Status: "PrinterError: out of paper"
|
||||
*Status: "PrinterError: toner cartridge missing or incorrect"
|
||||
*Status: "PrinterError: paper jam"
|
||||
*Status: "PrinterError: Cassette (250 Sheets): no paper tray"
|
||||
*Status: "PrinterError: Cassette (250 Sheets): out of paper"
|
||||
*Status: "PrinterError: Cassette (500 Sheets): no paper tray"
|
||||
*Status: "PrinterError: Cassette (500 Sheets): out of paper"
|
||||
*Status: "PrinterError: Multipurpose Tray: out of paper"
|
||||
*Status: "PrinterError: Envelope Feeder: out of paper"
|
||||
*Status: "PrinterError: Manual Feed: out of paper"
|
||||
*Status: "PrinterError: waiting for manual feed"
|
||||
*Status: "PrinterError: fixing temperature malfunction"
|
||||
*Status: "PrinterError: scanner motor malfunction"
|
||||
|
||||
*% Input Sources (format: %%[ status: <stat>; source: <one of these> ]%% )
|
||||
*Source: "Serial"
|
||||
*Source: "SerialB"
|
||||
*Source: "LocalTalk"
|
||||
*Source: "Parallel"
|
||||
*Source: "EtherTalk"
|
||||
|
||||
*% Printer Error (format: %%[ PrinterError: <one of these> ]%%)
|
||||
*PrinterError: "cover open"
|
||||
*PrinterError: "warming up"
|
||||
*PrinterError: "out of paper"
|
||||
*PrinterError: "toner cartridge missing or incorrect"
|
||||
*PrinterError: "paper jam"
|
||||
*PrinterError: "Cassette (250 Sheets): no paper tray"
|
||||
*PrinterError: "Cassette (250 Sheets): out of paper"
|
||||
*PrinterError: "Cassette (500 Sheets): no paper tray"
|
||||
*PrinterError: "Cassette (500 Sheets): out of paper"
|
||||
*PrinterError: "Multipurpose Tray: out of paper"
|
||||
*PrinterError: "Envelope Feeder: out of paper"
|
||||
*PrinterError: "Manual Feed: out of paper"
|
||||
*PrinterError: "waiting for manual feed"
|
||||
*PrinterError: "fixing temperature malfunction"
|
||||
*PrinterError: "scanner motor malfunction"
|
||||
|
||||
*%DeviceAdjustMatrix: "[1 0 0 1 0 0]"
|
||||
|
||||
*% Color Separation Information =====================
|
||||
|
||||
*DefaultColorSep: ProcessBlack.85lpi.600dpi/85 lpi / 600 dpi
|
||||
|
||||
*InkName: ProcessBlack/Process Black
|
||||
*InkName: CustomColor/Custom Color
|
||||
*InkName: ProcessCyan/Process Cyan
|
||||
*InkName: ProcessMagenta/Process Magenta
|
||||
*InkName: ProcessYellow/Process Yellow
|
||||
|
||||
*% For 60 lpi / 300 dpi ===============================
|
||||
|
||||
*ColorSepScreenAngle ProcessBlack.60lpi.300dpi/60 lpi / 300 dpi: "45"
|
||||
*ColorSepScreenAngle CustomColor.60lpi.300dpi/60 lpi / 300 dpi: "45"
|
||||
*ColorSepScreenAngle ProcessCyan.60lpi.300dpi/60 lpi / 300 dpi: "15"
|
||||
*ColorSepScreenAngle ProcessMagenta.60lpi.300dpi/60 lpi / 300 dpi: "75"
|
||||
*ColorSepScreenAngle ProcessYellow.60lpi.300dpi/60 lpi / 300 dpi: "0"
|
||||
|
||||
*ColorSepScreenFreq ProcessBlack.60lpi.300dpi/60 lpi / 300 dpi: "60"
|
||||
*ColorSepScreenFreq CustomColor.60lpi.300dpi/60 lpi / 300 dpi: "60"
|
||||
*ColorSepScreenFreq ProcessCyan.60lpi.300dpi/60 lpi / 300 dpi: "60"
|
||||
*ColorSepScreenFreq ProcessMagenta.60lpi.300dpi/60 lpi / 300 dpi: "60"
|
||||
*ColorSepScreenFreq ProcessYellow.60lpi.300dpi/60 lpi / 300 dpi: "60"
|
||||
|
||||
*% For 53 lpi / 300 dpi ===============================
|
||||
|
||||
*ColorSepScreenAngle ProcessBlack.53lpi.300dpi/53 lpi / 300 dpi: "45.0"
|
||||
*ColorSepScreenAngle CustomColor.53lpi.300dpi/53 lpi / 300 dpi: "45.0"
|
||||
*ColorSepScreenAngle ProcessCyan.53lpi.300dpi/53 lpi / 300 dpi: "71.5651"
|
||||
*ColorSepScreenAngle ProcessMagenta.53lpi.300dpi/53 lpi / 300 dpi: "18.4349"
|
||||
*ColorSepScreenAngle ProcessYellow.53lpi.300dpi/53 lpi / 300 dpi: "0.0"
|
||||
|
||||
*ColorSepScreenFreq ProcessBlack.53lpi.300dpi/53 lpi / 300 dpi: "53.033"
|
||||
*ColorSepScreenFreq CustomColor.53lpi.300dpi/53 lpi / 300 dpi: "53.033"
|
||||
*ColorSepScreenFreq ProcessCyan.53lpi.300dpi/53 lpi / 300 dpi: "47.4342"
|
||||
*ColorSepScreenFreq ProcessMagenta.53lpi.300dpi/53 lpi / 300 dpi: "47.4342"
|
||||
*ColorSepScreenFreq ProcessYellow.53lpi.300dpi/53 lpi / 300 dpi: "50.0"
|
||||
|
||||
*% For 85 lpi / 600 dpi (5,5,2,6,6,2,20/3,0) =====================
|
||||
|
||||
*ColorSepScreenAngle ProcessBlack.85lpi.600dpi/85 lpi / 600 dpi: "45.0"
|
||||
*ColorSepScreenAngle CustomColor.85lpi.600dpi/85 lpi / 600 dpi: "45.0"
|
||||
*ColorSepScreenAngle ProcessCyan.85lpi.600dpi/85 lpi / 600 dpi: "71.5651"
|
||||
*ColorSepScreenAngle ProcessMagenta.85lpi.600dpi/85 lpi / 600 dpi: "18.4349"
|
||||
*ColorSepScreenAngle ProcessYellow.85lpi.600dpi/85 lpi / 600 dpi: "0.0"
|
||||
|
||||
*ColorSepScreenFreq ProcessBlack.85lpi.600dpi/85 lpi / 600 dpi: "84.8528"
|
||||
*ColorSepScreenFreq CustomColor.85lpi.600dpi/85 lpi / 600 dpi: "84.8528"
|
||||
*ColorSepScreenFreq ProcessCyan.85lpi.600dpi/85 lpi / 600 dpi: "94.8683"
|
||||
*ColorSepScreenFreq ProcessMagenta.85lpi.600dpi/85 lpi / 600 dpi: "94.8683"
|
||||
*ColorSepScreenFreq ProcessYellow.85lpi.600dpi/85 lpi / 600 dpi: "30.0"
|
||||
|
||||
*ColorSepScreenProc ProcessYellow.85lpi.600dpi/85 lpi / 600 dpi: "
|
||||
{1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch
|
||||
1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch
|
||||
abs exch abs 2 copy add 1 gt {1 sub dup mul exch 1 sub dup mul add 1
|
||||
sub }{dup mul exch dup mul add 1 exch sub }ifelse }"
|
||||
*End
|
||||
|
||||
*% For 71 lpi / 600 dpi ===============================
|
||||
|
||||
*ColorSepScreenAngle ProcessBlack.71lpi.600dpi/71 lpi / 600 dpi: "45.0"
|
||||
*ColorSepScreenAngle CustomColor.71lpi.600dpi/71 lpi / 600 dpi: "45.0"
|
||||
*ColorSepScreenAngle ProcessCyan.71lpi.600dpi/71 lpi / 600 dpi: "71.5651"
|
||||
*ColorSepScreenAngle ProcessMagenta.71lpi.600dpi/71 lpi / 600 dpi: "18.4349"
|
||||
*ColorSepScreenAngle ProcessYellow.71lpi.600dpi/71 lpi / 600 dpi: "0.0"
|
||||
|
||||
*ColorSepScreenFreq ProcessBlack.71lpi.600dpi/71 lpi / 600 dpi: "70.7107"
|
||||
*ColorSepScreenFreq CustomColor.71lpi.600dpi/71 lpi / 600 dpi: "70.7107"
|
||||
*ColorSepScreenFreq ProcessCyan.71lpi.600dpi/71 lpi / 600 dpi: "63.2456"
|
||||
*ColorSepScreenFreq ProcessMagenta.71lpi.600dpi/71 lpi / 600 dpi: "63.2456"
|
||||
*ColorSepScreenFreq ProcessYellow.71lpi.600dpi/71 lpi / 600 dpi: "66.6667"
|
||||
|
||||
*% Produced by "bldppd42.ps" version 4.0 edit 11
|
||||
*% Last Edit Date: Mar 23 1994
|
||||
*% The byte count of this file should be exactly 022556 or 023212
|
||||
*% depending on the filesystem it resides in.
|
||||
*% end of PPD file for LaserWriter Pro 630
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
12345
|
||||
67890
|
||||
@@ -0,0 +1,4 @@
|
||||
abcdef
|
||||
ghijklmn
|
||||
opqrstu
|
||||
vwxyz.
|
||||
@@ -0,0 +1,22 @@
|
||||
Contents of directory "test"
|
||||
|
||||
PPDConfig UI Application
|
||||
- Application.cpp
|
||||
- Application.h
|
||||
- Application.rsrc
|
||||
- MsgConsts.h
|
||||
- PPDConfig.x86.proj (BeIDE project file)
|
||||
|
||||
Test command line application
|
||||
- Test.cpp
|
||||
- Test.h
|
||||
- Test.proj (BeIDE project file)
|
||||
- TestParser.cpp
|
||||
- TestScanner.cpp
|
||||
|
||||
Files used by test command line application:
|
||||
- aptollw1.ppd
|
||||
- include.ppd
|
||||
- main.ppd
|
||||
|
||||
File header.txt contains parts of a PPD file that are typically part of the "header".
|
||||
@@ -0,0 +1,14 @@
|
||||
SubDir HAIKU_TOP src tests add-ons print ppd ui ;
|
||||
|
||||
# SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
SubDirHdrs $(HAIKU_TOP) src tests add-ons print ppd model ;
|
||||
SubDirHdrs $(HAIKU_TOP) src tests add-ons print ppd parser ;
|
||||
|
||||
StaticLibrary
|
||||
libppdtest.a
|
||||
:
|
||||
PPDConfigView.cpp
|
||||
PrinterSelection.cpp
|
||||
UIUtils.cpp
|
||||
;
|
||||
@@ -0,0 +1,537 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "PPDConfigView.h"
|
||||
#include "PPDParser.h"
|
||||
#include "StatementListVisitor.h"
|
||||
#include "UIUtils.h"
|
||||
|
||||
#include <Box.h>
|
||||
#include <CheckBox.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuField.h>
|
||||
#include <MenuItem.h>
|
||||
#include <RadioButton.h>
|
||||
#include <ScrollView.h>
|
||||
#include <StringView.h>
|
||||
#include <Window.h>
|
||||
|
||||
// margin
|
||||
const float kLeftMargin = 3.0;
|
||||
const float kRightMargin = 3.0;
|
||||
const float kTopMargin = 3.0;
|
||||
const float kBottomMargin = 3.0;
|
||||
|
||||
// space between views
|
||||
const float kHorizontalSpace = 8.0;
|
||||
const float kVerticalSpace = 8.0;
|
||||
|
||||
// Message what values
|
||||
const uint32 kMsgBooleanChanged = 'bool';
|
||||
const uint32 kMsgStringChanged = 'strc';
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class DefaultValueExtractor : public StatementListVisitor
|
||||
{
|
||||
BMessage fDefaultValues;
|
||||
|
||||
public:
|
||||
void DoDefault(Statement* statement)
|
||||
{
|
||||
const char* keyword = statement->GetKeywordString();
|
||||
const char* value = statement->GetValueString();
|
||||
if (keyword != NULL && value != NULL) {
|
||||
fDefaultValues.AddString(keyword, value);
|
||||
}
|
||||
}
|
||||
|
||||
const BMessage& GetDefaultValues()
|
||||
{
|
||||
return fDefaultValues;
|
||||
}
|
||||
};
|
||||
|
||||
class CategoryBuilder : public StatementListVisitor
|
||||
{
|
||||
BOutlineListView* fCategories;
|
||||
|
||||
public:
|
||||
CategoryBuilder(BOutlineListView* categories)
|
||||
: fCategories(categories)
|
||||
{}
|
||||
|
||||
void AddStatement(const char* text, Statement* statement)
|
||||
{
|
||||
if (text != NULL) {
|
||||
BStringItem* item = new CategoryItem(text, statement, GetLevel());
|
||||
fCategories->AddItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void BeginGroup(GroupStatement* group)
|
||||
{
|
||||
const char* translation = group->GetGroupTranslation();
|
||||
const char* name = group->GetGroupName();
|
||||
|
||||
const char* text = NULL;
|
||||
if (translation != NULL) {
|
||||
text = translation;
|
||||
} else {
|
||||
text = name;
|
||||
}
|
||||
|
||||
AddStatement(text, group->GetStatement());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
DetailsBuilder adds views to the details view and sets the
|
||||
value to the one specified in the settings.
|
||||
|
||||
The group type determines the view to be used for user input:
|
||||
Type Input
|
||||
---------------------
|
||||
Boolean BRadioButton
|
||||
PickOne BMenuField
|
||||
PickMany BCheckBox
|
||||
Unknown BCheckBox
|
||||
*/
|
||||
class DetailsBuilder : public StatementListVisitor
|
||||
{
|
||||
BView* fParent;
|
||||
BView* fDetails;
|
||||
BRect fBounds;
|
||||
const char* fKeyword;
|
||||
const char* fValue;
|
||||
GroupStatement fGroup;
|
||||
BMenu* fMenu;
|
||||
BMenuField* fMenuField;
|
||||
const BMessage& fSettings;
|
||||
|
||||
void AddView(BView* view);
|
||||
|
||||
BMessage* GetMessage(uint32 what, const char* option);
|
||||
|
||||
public:
|
||||
DetailsBuilder(BView* parent, BView* details, BRect bounds, Statement* group, const BMessage& settings);
|
||||
|
||||
BRect GetBounds() { return fBounds; }
|
||||
|
||||
void Visit(StatementList* list);
|
||||
|
||||
void DoValue(Statement* statement);
|
||||
};
|
||||
|
||||
void DetailsBuilder::AddView(BView* view)
|
||||
{
|
||||
if (view != NULL) {
|
||||
fDetails->AddChild(view);
|
||||
view->ResizeToPreferred();
|
||||
|
||||
fBounds.OffsetBy(0, view->Bounds().Height()+1);
|
||||
|
||||
BControl* control = dynamic_cast<BControl*>(view);
|
||||
if (control != NULL) {
|
||||
control->SetTarget(fParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DetailsBuilder::DetailsBuilder(BView* parent, BView* details, BRect bounds, Statement* group, const BMessage& settings)
|
||||
: fParent(parent)
|
||||
, fDetails(details)
|
||||
, fBounds(bounds)
|
||||
, fGroup(group)
|
||||
, fMenu(NULL)
|
||||
, fMenuField(NULL)
|
||||
, fSettings(settings)
|
||||
{
|
||||
fKeyword = fGroup.GetGroupName();
|
||||
|
||||
if (fKeyword == NULL) return;
|
||||
|
||||
fValue = settings.FindString(fKeyword);
|
||||
|
||||
const char* label = fGroup.GetGroupTranslation();
|
||||
if (label == NULL) {
|
||||
label = fKeyword;
|
||||
}
|
||||
|
||||
BView* view = NULL;
|
||||
if (fGroup.GetType() == GroupStatement::kPickOne) {
|
||||
fMenu = new BMenu("<pick one>");
|
||||
fMenu->SetRadioMode(true);
|
||||
fMenu->SetLabelFromMarked(true);
|
||||
fMenuField = new BMenuField(fBounds, "menuField", label, fMenu);
|
||||
view = fMenuField;
|
||||
} else if (fGroup.GetType() == GroupStatement::kBoolean) {
|
||||
BMessage* message = GetMessage(kMsgBooleanChanged, "");
|
||||
BCheckBox* cb = new BCheckBox(fBounds, "", label, message);
|
||||
view = cb;
|
||||
cb->SetValue((fValue != NULL && strcmp(fValue, "True") == 0)
|
||||
? B_CONTROL_ON
|
||||
: B_CONTROL_OFF);
|
||||
}
|
||||
|
||||
AddView(view);
|
||||
}
|
||||
|
||||
void DetailsBuilder::Visit(StatementList* list)
|
||||
{
|
||||
if (fKeyword == NULL) return;
|
||||
|
||||
StatementListVisitor::Visit(list);
|
||||
}
|
||||
|
||||
BMessage* DetailsBuilder::GetMessage(uint32 what, const char* option)
|
||||
{
|
||||
BMessage* message = new BMessage(what);
|
||||
message->AddString("keyword", fKeyword);
|
||||
|
||||
if (option != NULL) {
|
||||
message->AddString("option", option);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
void DetailsBuilder::DoValue(Statement* statement)
|
||||
{
|
||||
if (GetLevel() != 0) return;
|
||||
if (strcmp(fKeyword, statement->GetKeywordString()) != 0) return;
|
||||
|
||||
const char* text = NULL;
|
||||
const char* option = statement->GetOptionString();
|
||||
if (statement->GetTranslationString() != NULL) {
|
||||
text = statement->GetTranslationString();
|
||||
} else if (option != NULL) {
|
||||
text = option;
|
||||
}
|
||||
|
||||
if (text == NULL) return;
|
||||
|
||||
BView* view = NULL;
|
||||
BMessage* message = NULL;
|
||||
|
||||
if (fGroup.GetType() == GroupStatement::kPickMany ||
|
||||
fGroup.GetType() == GroupStatement::kUnknown) {
|
||||
message = GetMessage(kMsgStringChanged, option);
|
||||
view = new BCheckBox(fBounds, "", text, message);
|
||||
} else if (fGroup.GetType() == GroupStatement::kPickOne) {
|
||||
message = GetMessage(kMsgStringChanged, option);
|
||||
BMenuItem* item = new BMenuItem(text, message);
|
||||
item->SetTarget(fParent);
|
||||
fMenu->AddItem(item);
|
||||
if (fValue != NULL && option != NULL && strcmp(fValue, option) == 0) {
|
||||
item->SetMarked(true);
|
||||
}
|
||||
}
|
||||
|
||||
AddView(view);
|
||||
}
|
||||
|
||||
#define kBoxHeight 20
|
||||
#define kBoxBottomMargin 4
|
||||
#define kBoxLeftMargin 8
|
||||
#define kBoxRightMargin 8
|
||||
|
||||
#define kItemLeftMargin 5
|
||||
#define kItemRightMargin 5
|
||||
|
||||
class PPDBuilder : public StatementListVisitor
|
||||
{
|
||||
BView* fParent;
|
||||
BView* fView;
|
||||
BRect fBounds;
|
||||
BMessage& fSettings;
|
||||
BList fNestedBoxes;
|
||||
|
||||
bool IsTop()
|
||||
{
|
||||
return fNestedBoxes.CountItems() == 0;
|
||||
}
|
||||
|
||||
void Push(BView* view)
|
||||
{
|
||||
fNestedBoxes.AddItem(view);
|
||||
}
|
||||
|
||||
void Pop()
|
||||
{
|
||||
fNestedBoxes.RemoveItem((int32)fNestedBoxes.CountItems()-1);
|
||||
}
|
||||
|
||||
BView* GetView()
|
||||
{
|
||||
if (IsTop()) {
|
||||
return fView;
|
||||
} else {
|
||||
return (BView*)fNestedBoxes.ItemAt(fNestedBoxes.CountItems()-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
BRect GetControlBounds()
|
||||
{
|
||||
if (IsTop()) {
|
||||
BRect bounds(fBounds);
|
||||
bounds.left += kItemLeftMargin /** GetLevel()*/;
|
||||
bounds.right -= kItemRightMargin /** GetLevel()*/;
|
||||
return bounds;
|
||||
}
|
||||
|
||||
BView* box = GetView();
|
||||
BRect bounds(box->Bounds());
|
||||
bounds.top = bounds.bottom - kBoxBottomMargin;
|
||||
bounds.bottom = bounds.top + kBoxHeight;
|
||||
bounds.left += kBoxLeftMargin;
|
||||
bounds.right -= kBoxRightMargin;
|
||||
return bounds;
|
||||
}
|
||||
|
||||
bool IsUIGroup(GroupStatement* group)
|
||||
{
|
||||
return group->IsUIGroup() || group->IsJCL();
|
||||
}
|
||||
|
||||
void UpdateParentHeight(float height)
|
||||
{
|
||||
if (IsTop()) {
|
||||
fBounds.OffsetBy(0, height);
|
||||
} else {
|
||||
BView* parent = GetView();
|
||||
parent->ResizeBy(0, height);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
PPDBuilder(BView* parent, BView* view, BMessage& settings)
|
||||
: fParent(parent)
|
||||
, fView(view)
|
||||
, fBounds(view->Bounds())
|
||||
, fSettings(settings)
|
||||
{
|
||||
RemoveChildren(view);
|
||||
fBounds.OffsetTo(0, 0);
|
||||
fBounds.left += kLeftMargin;
|
||||
fBounds.top += kTopMargin;
|
||||
fBounds.right -= kRightMargin;
|
||||
}
|
||||
|
||||
BRect GetBounds()
|
||||
{
|
||||
return BRect(0, 0, fView->Bounds().Width(), fBounds.top);
|
||||
}
|
||||
|
||||
void AddUIGroup(const char* text, Statement* statement)
|
||||
{
|
||||
if (statement->GetChildren() == NULL) return;
|
||||
DetailsBuilder builder(fParent, GetView(), GetControlBounds(), statement, fSettings);
|
||||
builder.Visit(statement->GetChildren());
|
||||
|
||||
if (IsTop()) {
|
||||
fBounds.OffsetTo(fBounds.left, builder.GetBounds().top);
|
||||
} else {
|
||||
BView* box = GetView();
|
||||
box->ResizeTo(box->Bounds().Width(), builder.GetBounds().top + kBoxBottomMargin);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGroup(const char* text)
|
||||
{
|
||||
if (text != NULL) {
|
||||
BBox* box = new BBox(GetControlBounds(), text);
|
||||
box->SetLabel(text);
|
||||
GetView()->AddChild(box);
|
||||
Push(box);
|
||||
box->ResizeTo(box->Bounds().Width(), kBoxHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void CloseGroup()
|
||||
{
|
||||
if (!IsTop()) {
|
||||
BView* box = GetView();
|
||||
Pop();
|
||||
UpdateParentHeight(box->Bounds().Height());
|
||||
}
|
||||
}
|
||||
|
||||
void BeginGroup(GroupStatement* group)
|
||||
{
|
||||
const char* translation = group->GetGroupTranslation();
|
||||
const char* name = group->GetGroupName();
|
||||
|
||||
const char* text = NULL;
|
||||
if (translation != NULL) {
|
||||
text = translation;
|
||||
} else {
|
||||
text = name;
|
||||
}
|
||||
|
||||
if (IsUIGroup(group)) {
|
||||
AddUIGroup(text, group->GetStatement());
|
||||
} else {
|
||||
OpenGroup(text);
|
||||
}
|
||||
}
|
||||
|
||||
void EndGroup(GroupStatement* group)
|
||||
{
|
||||
if (!IsUIGroup(group)) {
|
||||
CloseGroup();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PPDConfigView::PPDConfigView(BRect bounds, const char *name, uint32 resizeMask, uint32 flags)
|
||||
: BView(bounds, name, resizeMask, flags)
|
||||
, fPPD(NULL)
|
||||
{
|
||||
// add category outline list view
|
||||
bounds.OffsetTo(0, 0);
|
||||
BRect listBounds(bounds.left + kLeftMargin, bounds.top + kTopMargin,
|
||||
bounds.right - kHorizontalSpace, bounds.bottom - kBottomMargin);
|
||||
listBounds.right -= B_V_SCROLL_BAR_WIDTH;
|
||||
listBounds.bottom -= B_H_SCROLL_BAR_HEIGHT;
|
||||
|
||||
BStringView* label = new BStringView(listBounds, "printer-settings", "Printer Settings:");
|
||||
AddChild(label);
|
||||
label->ResizeToPreferred();
|
||||
|
||||
listBounds.top += label->Bounds().bottom + 5;
|
||||
|
||||
// add details view
|
||||
fDetails = new BView(listBounds, "details", B_FOLLOW_ALL_SIDES, B_WILL_DRAW);
|
||||
fDetails->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
|
||||
BScrollView* scrollView = new BScrollView("details-scroll-view",
|
||||
fDetails, B_FOLLOW_ALL_SIDES, 0, true, true);
|
||||
|
||||
AddChild(scrollView);
|
||||
}
|
||||
|
||||
void SetScrollBar(BScrollBar* scroller, float contents, float client)
|
||||
{
|
||||
if (scroller != NULL) {
|
||||
float extent = contents - client;
|
||||
if (extent >= 0) {
|
||||
scroller->SetRange(0, extent);
|
||||
scroller->SetProportion(1-extent / contents);
|
||||
scroller->SetSteps(20, client);
|
||||
} else {
|
||||
scroller->SetRange(0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PPDConfigView::FillCategories()
|
||||
{
|
||||
if (fPPD == NULL) return;
|
||||
|
||||
PPDBuilder builder(this, fDetails, fSettings);
|
||||
builder.Visit(fPPD);
|
||||
BScrollBar* scroller = fDetails->ScrollBar(B_VERTICAL);
|
||||
SetScrollBar(scroller, builder.GetBounds().Height(), fDetails->Bounds().Height());
|
||||
scroller = fDetails->ScrollBar(B_HORIZONTAL);
|
||||
SetScrollBar(scroller, builder.GetBounds().Width(), fDetails->Bounds().Width());
|
||||
}
|
||||
|
||||
void PPDConfigView::FillDetails(Statement* statement)
|
||||
{
|
||||
RemoveChildren(fDetails);
|
||||
|
||||
if (statement == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
StatementList* children= statement->GetChildren();
|
||||
if (children == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BRect bounds(fDetails->Bounds());
|
||||
bounds.OffsetTo(kLeftMargin, kTopMargin);
|
||||
DetailsBuilder builder(this, fDetails, bounds, statement, fSettings);
|
||||
builder.Visit(children);
|
||||
}
|
||||
|
||||
void PPDConfigView::BooleanChanged(BMessage* msg)
|
||||
{
|
||||
const char* keyword = msg->FindString("keyword");
|
||||
|
||||
int32 value;
|
||||
if (msg->FindInt32("be:value", &value) == B_OK) {
|
||||
const char* option;
|
||||
if (value) {
|
||||
option = "True";
|
||||
} else {
|
||||
option = "False";
|
||||
}
|
||||
fSettings.ReplaceString(keyword, option);
|
||||
}
|
||||
}
|
||||
|
||||
void PPDConfigView::StringChanged(BMessage* msg)
|
||||
{
|
||||
const char* keyword = msg->FindString("keyword");
|
||||
const char* option = msg->FindString("option");
|
||||
|
||||
if (keyword != NULL && keyword != NULL) {
|
||||
fSettings.ReplaceString(keyword, option);
|
||||
}
|
||||
}
|
||||
|
||||
void PPDConfigView::MessageReceived(BMessage* msg)
|
||||
{
|
||||
switch (msg->what) {
|
||||
case kMsgBooleanChanged: BooleanChanged(msg);
|
||||
break;
|
||||
case kMsgStringChanged: StringChanged(msg);
|
||||
break;
|
||||
}
|
||||
|
||||
BView::MessageReceived(msg);
|
||||
}
|
||||
|
||||
void PPDConfigView::SetupSettings(const BMessage& currentSettings)
|
||||
{
|
||||
DefaultValueExtractor extractor;
|
||||
extractor.Visit(fPPD);
|
||||
|
||||
const BMessage &defaultValues(extractor.GetDefaultValues());
|
||||
fSettings.MakeEmpty();
|
||||
|
||||
char* name;
|
||||
type_code code;
|
||||
for (int32 index = 0; defaultValues.GetInfo(B_STRING_TYPE, index, &name, &code) == B_OK; index ++) {
|
||||
const char* value = currentSettings.FindString(name);
|
||||
if (value == NULL) {
|
||||
value = defaultValues.FindString(name);
|
||||
}
|
||||
if (value != NULL) {
|
||||
fSettings.AddString(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PPDConfigView::Set(const char* file, const BMessage& currentSettings)
|
||||
{
|
||||
delete fPPD;
|
||||
|
||||
PPDParser parser(file);
|
||||
fPPD = parser.ParseAll();
|
||||
if (fPPD == NULL) {
|
||||
fprintf(stderr, "Parsing error (%s): %s\n", file, parser.GetErrorMessage());
|
||||
}
|
||||
|
||||
SetupSettings(currentSettings);
|
||||
FillCategories();
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _PPD_CONFIG_VIEW_H
|
||||
#define _PPD_CONFIG_VIEW_H
|
||||
|
||||
#include "PPD.h"
|
||||
|
||||
#include <View.h>
|
||||
#include <ListItem.h>
|
||||
#include <OutlineListView.h>
|
||||
|
||||
class CategoryItem : public BStringItem
|
||||
{
|
||||
private:
|
||||
Statement* fStatement;
|
||||
|
||||
public:
|
||||
CategoryItem(const char* text, Statement* statement, uint32 level)
|
||||
: BStringItem(text, level)
|
||||
, fStatement(statement)
|
||||
{
|
||||
}
|
||||
|
||||
Statement* GetStatement() { return fStatement; }
|
||||
};
|
||||
|
||||
class PPDConfigView : public BView {
|
||||
private:
|
||||
PPD* fPPD;
|
||||
|
||||
BView* fDetails;
|
||||
BMessage fSettings;
|
||||
|
||||
void SetupSettings(const BMessage& settings);
|
||||
|
||||
void BooleanChanged(BMessage* msg);
|
||||
void StringChanged(BMessage* msg);
|
||||
|
||||
public:
|
||||
PPDConfigView(BRect rect, const char *name, uint32 resizeMask, uint32 flags);
|
||||
|
||||
// The view has to be attached to a window when this
|
||||
// method is called.
|
||||
void Set(const char* ppdFile, const BMessage& settings);
|
||||
const BMessage& GetSettings();
|
||||
|
||||
void FillCategories();
|
||||
void FillDetails(Statement* statement);
|
||||
void MessageReceived(BMessage* msg);
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "PrinterSelection.h"
|
||||
#include "PPDParser.h"
|
||||
#include "StatementListVisitor.h"
|
||||
#include "UIUtils.h"
|
||||
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include <ScrollView.h>
|
||||
#include <StringView.h>
|
||||
|
||||
// margin
|
||||
const float kLeftMargin = 3.0;
|
||||
const float kRightMargin = 3.0;
|
||||
const float kTopMargin = 3.0;
|
||||
const float kBottomMargin = 3.0;
|
||||
|
||||
// space between views
|
||||
const float kHorizontalSpace = 8.0;
|
||||
const float kVerticalSpace = 8.0;
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
PrinterSelectionView::PrinterSelectionView(BRect bounds, const char *name, uint32 resizeMask, uint32 flags)
|
||||
: BView(bounds, name, resizeMask, flags)
|
||||
{
|
||||
// add vendor list view
|
||||
bounds.OffsetTo(0, 0);
|
||||
BRect listBounds(bounds.left + kLeftMargin, bounds.top + kTopMargin,
|
||||
bounds.right / 3.0 - kHorizontalSpace / 2, bounds.bottom - kBottomMargin);
|
||||
listBounds.right -= B_V_SCROLL_BAR_WIDTH;
|
||||
listBounds.bottom -= B_H_SCROLL_BAR_HEIGHT;
|
||||
|
||||
BStringView* label = new BStringView(listBounds, "vendors-label", "Vendors:");
|
||||
AddChild(label);
|
||||
label->ResizeToPreferred();
|
||||
|
||||
listBounds.top += label->Bounds().bottom + 5;
|
||||
|
||||
fVendors = new BListView(listBounds, "vendors", B_SINGLE_SELECTION_LIST,
|
||||
B_FOLLOW_ALL);
|
||||
FillVendors();
|
||||
|
||||
BScrollView* scrollView = new BScrollView("vendors-scroll-view",
|
||||
fVendors, B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, 0, true, true);
|
||||
|
||||
AddChild(scrollView);
|
||||
|
||||
// add details view
|
||||
BRect printerBounds(listBounds);
|
||||
printerBounds.left = B_V_SCROLL_BAR_WIDTH + printerBounds.right + kHorizontalSpace;
|
||||
printerBounds.right = bounds.right - kRightMargin - B_V_SCROLL_BAR_WIDTH;
|
||||
printerBounds.top = bounds.top + kTopMargin;
|
||||
label = new BStringView(printerBounds, "printers-label", "Printers:");
|
||||
AddChild(label);
|
||||
label->ResizeToPreferred();
|
||||
|
||||
BRect detailBounds(listBounds);
|
||||
detailBounds.left = B_V_SCROLL_BAR_WIDTH + detailBounds.right + kHorizontalSpace;
|
||||
detailBounds.right = bounds.right - kRightMargin - B_V_SCROLL_BAR_WIDTH;
|
||||
fPrinters = new BListView(detailBounds, "printers", B_SINGLE_SELECTION_LIST,
|
||||
B_FOLLOW_ALL);
|
||||
|
||||
scrollView = new BScrollView("printers-scroll-view",
|
||||
fPrinters, B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, 0, true, true);
|
||||
|
||||
AddChild(scrollView);
|
||||
}
|
||||
|
||||
void PrinterSelectionView::AttachedToWindow()
|
||||
{
|
||||
fVendors->SetSelectionMessage(new BMessage('sel'));
|
||||
fVendors->SetTarget(this);
|
||||
|
||||
fPrinters->SetSelectionMessage(new BMessage('prnt'));
|
||||
fPrinters->SetTarget(this);
|
||||
}
|
||||
|
||||
|
||||
void PrinterSelectionView::FillVendors()
|
||||
{
|
||||
BDirectory directory("/boot/beos/etc/ppd");
|
||||
BEntry entry;
|
||||
while (directory.GetNextEntry(&entry) == B_OK) {
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
entry.GetName(name);
|
||||
BPath path;
|
||||
entry.GetPath(&path);
|
||||
fVendors->AddItem(new FileItem(name, path.Path()));
|
||||
}
|
||||
}
|
||||
|
||||
void PrinterSelectionView::FillPrinters(const char* vendor)
|
||||
{
|
||||
MakeEmpty(fPrinters);
|
||||
|
||||
BList printers;
|
||||
BDirectory directory(vendor);
|
||||
BEntry entry;
|
||||
while (directory.GetNextEntry(&entry) == B_OK) {
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
entry.GetName(name);
|
||||
BPath path;
|
||||
entry.GetPath(&path);
|
||||
|
||||
PPDParser parser(path.Path());
|
||||
PPD* ppd = parser.ParseHeader();
|
||||
if (parser.HasWarning()) {
|
||||
fprintf(stderr, "Warning(s): %s", parser.GetWarningMessage());
|
||||
}
|
||||
|
||||
if (ppd != NULL) {
|
||||
|
||||
BString label;
|
||||
const char* s;
|
||||
s = ppd->GetValue("ModelName");
|
||||
if (s != NULL) {
|
||||
label << s;
|
||||
}
|
||||
s = ppd->GetValue("PCFileName");
|
||||
if (s != NULL) {
|
||||
label << " [" << s << "]";
|
||||
}
|
||||
s = ppd->GetValue("Manufacturer");
|
||||
if (s != NULL) {
|
||||
label << " (" << s << ")";
|
||||
}
|
||||
printers.AddItem(new FileItem(label.String(), path.Path()));
|
||||
delete ppd;
|
||||
} else {
|
||||
fprintf(stderr, "Parsing error (%s)\n%s\n", path.Path(),
|
||||
parser.GetErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
fPrinters->AddList(&printers);
|
||||
}
|
||||
|
||||
void PrinterSelectionView::MessageReceived(BMessage* msg)
|
||||
{
|
||||
int32 index;
|
||||
switch (msg->what) {
|
||||
case 'sel':
|
||||
if (msg->FindInt32("index", &index) == B_OK) {
|
||||
FileItem* file = (FileItem*)fVendors->ItemAt(index);
|
||||
if (file != NULL) {
|
||||
FillPrinters(file->GetFile());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'prnt':
|
||||
if (msg->FindInt32("index", &index) == B_OK) {
|
||||
FileItem* file = (FileItem*)fPrinters->ItemAt(index);
|
||||
if (file != NULL) {
|
||||
BMessage copy(*Message());
|
||||
copy.AddString("file", file->GetFile());
|
||||
InvokeNotify(©);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
BView::MessageReceived(msg);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _PRINTER_SELECTION_H
|
||||
#define _PRINTER_SELECTION_H
|
||||
|
||||
#include "PPD.h"
|
||||
|
||||
#include <Invoker.h>
|
||||
#include <View.h>
|
||||
#include <ListItem.h>
|
||||
#include <ListView.h>
|
||||
|
||||
class FileItem : public BStringItem
|
||||
{
|
||||
private:
|
||||
BString fFile;
|
||||
|
||||
public:
|
||||
FileItem(const char* label, const char* file)
|
||||
: BStringItem(label)
|
||||
, fFile(file)
|
||||
{
|
||||
}
|
||||
|
||||
const char* GetFile() { return fFile.String(); }
|
||||
};
|
||||
|
||||
class PrinterSelectionView : public BView, public BInvoker
|
||||
{
|
||||
private:
|
||||
BListView* fVendors;
|
||||
BListView* fPrinters;
|
||||
|
||||
public:
|
||||
PrinterSelectionView(BRect rect, const char *name, uint32 resizeMask, uint32 flags);
|
||||
|
||||
void AttachedToWindow();
|
||||
|
||||
void FillVendors();
|
||||
void FillPrinters(const char* vendor);
|
||||
void MessageReceived(BMessage* msg);
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#include "UIUtils.h"
|
||||
|
||||
void MakeEmpty(BListView* list)
|
||||
{
|
||||
if (list != NULL) {
|
||||
BListItem* item;
|
||||
while ((item = list->RemoveItem((int32)0)) != NULL) {
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveChildren(BView* view)
|
||||
{
|
||||
if (view != NULL) {
|
||||
BView* child;
|
||||
while ((child = view->ChildAt(0)) != NULL) {
|
||||
child->RemoveSelf();
|
||||
delete child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2008, Haiku.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Pfeiffer <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _UI_UTILS_H
|
||||
#define _UI_UTILS_H
|
||||
|
||||
#include <ListView.h>
|
||||
|
||||
void MakeEmpty(BListView* list);
|
||||
void RemoveChildren(BView* view);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user