Tizen 2.1 base
[platform/upstream/hplip.git] / prnt / hpijs / printerfactory.cpp
1 /*****************************************************************************\
2   Copyright (c) 2002 - 2002, Hewlett-Packard Co.
3   All rights reserved.
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions
7   are met:
8   1. Redistributions of source code must retain the above copyright
9      notice, this list of conditions and the following disclaimer.
10   2. Redistributions in binary form must reproduce the above copyright
11      notice, this list of conditions and the following disclaimer in the
12      documentation and/or other materials provided with the distribution.
13   3. Neither the name of Hewlett-Packard nor the names of its
14      contributors may be used to endorse or promote products derived
15      from this software without specific prior written permission.
16
17   THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
18   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
20   NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22   TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 \*****************************************************************************/
28 // PrinterFactory.cpp - Morpheus component code base
29
30 #include "header.h"
31 #include <string.h>
32 #include "printerfactory.h"
33
34 APDK_BEGIN_NAMESPACE
35
36 PrinterFactory* PrinterFactory::s_Instance = NULL;   // enforce the singleton
37 PrinterFactory::ProxyListElement* PrinterFactory::s_ProxyList = NULL;
38 unsigned int PrinterFactory::s_uFamilyCount = 0;
39 unsigned int PrinterFactory::s_uPrinterCount = 0;
40
41 extern void HP_strcat(char* str1, const char* str2);
42
43 //PrinterFactory
44 //! Constructor for PrinterFactory
45 /*!
46 ******************************************************************************/
47 PrinterFactory::PrinterFactory
48 (
49 )
50 {
51     TRACE("PF::PF\n");
52     // the static factory is coming on-line, do what you need here.
53     TRACE("PF - static factory construction complete\n");
54 } //PrinterFactory
55
56
57 //~PrinterFactory
58 //! Destructor for PrinterFactory
59 /*!
60 ******************************************************************************/
61 PrinterFactory::~PrinterFactory
62 (
63 )
64 {
65     TRACE("PF::~PF - static factory destructing\n");
66     ProxyListElement* t_ListEntry;
67     while (s_ProxyList)
68     {
69         TRACE(" - deleting %s from factory list\n", s_ProxyList->printerProxyElement->GetFamilyName());
70         t_ListEntry = s_ProxyList;
71         s_ProxyList = t_ListEntry->next;
72         delete t_ListEntry;
73     }
74     s_Instance = NULL;  // factory is gone
75     TRACE("finished PF::~PF\n");
76 } //~PrinterFactory
77
78
79 //Register
80 //! Register proxy classes for printer families
81 /*!
82 This method is used by the constuctor of the PrinterProxy subclasses to
83 register themselves with the factory.  They call Register(this) to pass
84 themselves to the factory.
85 ******************************************************************************/
86 void PrinterFactory::Register
87 (
88     const PrinterProxy* thePrinterProxy         //!< [in]pointer to the PrinterProxy
89 )
90 {
91     // use the first registration of a printer proxy to force the instantiation
92     // of the only PrinterFactory
93     if (s_Instance == NULL)
94     {
95         TRACE("PF::Register - asking for new factory\n");
96         // create the singleton
97         s_Instance = new PrinterFactory;
98     }
99
100     TRACE("PF::Register\n");
101     // we know we'll need an entry in the list so create it first
102     ProxyListElement* t_ListEntry = new(ProxyListElement);
103     if (t_ListEntry == NULL)
104     {
105         // we have a problem - the driver is not running yet
106         // the RTL is registering these static printer proxy servers and
107         // the main code hasn't started yet.
108         return;
109     }
110     // this list works so simply because we don't care about the order
111     // and we always insert the next entry before the current head.
112     t_ListEntry->printerProxyElement = thePrinterProxy;
113     t_ListEntry->next = s_ProxyList;
114     s_ProxyList = t_ListEntry;
115     s_uFamilyCount++;
116     s_uPrinterCount += thePrinterProxy->GetModelCount();
117
118     TRACE("PF::Register %s registered with PrinterFactory\n", thePrinterProxy->GetFamilyName());
119     TRACE("Printers supported by class are:\n");
120     MODEL_HANDLE myHandle = thePrinterProxy->StartModelNameEnum();
121     const char* printerName;
122     while ((printerName = thePrinterProxy->GetNextModelName(myHandle)))
123     {
124         TRACE("     %s\n", printerName);
125     }
126 } //Register
127
128
129 //UnRegister
130 //! UnRegister proxy classes for printer families
131 /*!
132 PrinterProxy subclasses use this to unregister themselves with their destuctor
133 executes.
134 ******************************************************************************/
135 void PrinterFactory::UnRegister
136 (
137     const PrinterProxy* thePrinterProxy     //!< [in]pointer to the PrinterProxy to unregister
138 )
139 {
140     // use the first registration of a printer proxy to force the instantiation
141     // of the only PrinterFactory
142     if (s_Instance == NULL)
143     {
144         TRACE("Unregistering a PrinterProxy when factory does not exist\n");
145         return;
146     }
147
148     TRACE("PF::UnRegister %s\n", thePrinterProxy->GetFamilyName());
149     if (s_ProxyList == NULL)
150     {
151         TRACE("PF::UnRegister - Printer Factory printer list is empty!\n");
152     }
153
154     ProxyListElement* prevListEntry = NULL;
155     ProxyListElement* t_ListEntry = s_ProxyList;
156     bool bFound = false;
157
158     while ((t_ListEntry) && (!bFound))
159     {
160         if (t_ListEntry->printerProxyElement == thePrinterProxy)
161         {
162             TRACE("We found the matching proxy by address\n");
163             bFound = true;
164             if (prevListEntry != NULL) //somewhere in list
165             {
166                 prevListEntry->next = t_ListEntry->next;
167             }
168             else    // at head of list
169             {
170                 s_ProxyList = t_ListEntry->next;
171             }
172             delete t_ListEntry;
173             s_uFamilyCount--;
174             s_uPrinterCount -= thePrinterProxy->GetModelCount();
175         }
176         prevListEntry = t_ListEntry;
177         t_ListEntry = t_ListEntry->next;
178     }
179     TRACE("PF::UnRegister removed %s from PrinterFactory\n", thePrinterProxy->GetFamilyName());
180     TRACE("PF::UnRegister - factory now supports %d families and %d printers\n",
181         s_uFamilyCount,
182         s_uPrinterCount);
183
184     if (s_ProxyList == NULL)
185     {
186         TRACE("PF::UnRegister asking for deletion of empty Factory\n");
187         delete PrinterFactory::GetInstance();
188     }
189 } //UnRegister
190
191
192 //GetNextFamilyName
193 //! return the next familiy name that is in the factory
194 /*!
195 Move to the next family in the factory and then return the name of that family.
196 This moved to the next family first!
197 FAMILY_HANDLE is changed to the next family.  If there are no more families in
198 the factory then FAMILY_HANDLE will be NULL.
199
200 \return
201 name of the next family in the factory<br>
202 NULL if there are no more families in the factory
203 ******************************************************************************/
204 const char* PrinterFactory::GetNextFamilyName
205 (
206     FAMILY_HANDLE& theFamilyHandle          //!< [in][out]handle to the current family
207 ) const
208 {
209     TRACE("PF::GetNextFamilyName()\n");
210     if (nextFamily(theFamilyHandle))
211     {
212         return getPrinterProxy(theFamilyHandle)->GetFamilyName();
213     }
214     else
215     {
216         return NULL;
217     }
218 } //GetNextFamilyName
219
220
221 //GetFamilyName
222 //! return the family namne that supports the printer
223 /*!
224 \return
225 the name of the family that supports the printer name passed in.  May be NULL
226 if there is no family in the factory that supports the printer name.
227 ******************************************************************************/
228 const char* PrinterFactory::GetFamilyName
229 (
230     const char* thePrinterName                  //!< [in] name of the printer model
231 ) const
232 {
233     const char* szFamilyName = NULL;
234     FAMILY_HANDLE myFamilyHandle = FindDevIdMatch(thePrinterName);
235     if (myFamilyHandle)
236     {
237         szFamilyName = getPrinterProxy(myFamilyHandle)->GetFamilyName();
238     }
239     return szFamilyName;
240 } //GetFamilyName
241
242 //NextModel
243 //! return the next model name for the current family that is in the factory
244 /*!
245 MODEL_HANDLE is updated durint this processes
246 \return
247 Name of the next model that this family supports.  Will be NULL at the end of
248 the model list.
249 ******************************************************************************/
250 const char* PrinterFactory::GetNextModelName
251 (
252     FAMILY_HANDLE theFamilyHandle,          //!< [in] handle to the current family
253     MODEL_HANDLE& theModelHandle            //!< [in][out] handle to the current model
254 ) const
255 {
256     TRACE("PF::GetNextModelName()\n");
257     const char* szModelName = NULL;
258     if (theFamilyHandle == NULL)
259     {
260         theModelHandle = NULL;
261     }
262     else
263     {
264         szModelName = getPrinterProxy(theFamilyHandle)->GetNextModelName(theModelHandle);
265     }
266     return szModelName;
267 } //GetNextModelName
268
269
270 //GetNextPrinterName
271 //! return the next printer name in the factory
272 /*!
273 This returns the next printer (model) name supported in the factory.  This
274 iterates over the whole factory without regard to families.  PRINTER_HANDLE is
275 updated during this process.
276
277 \return
278 Name of the printer in the factory.  Will be NULL after all the printers in the
279 factory have been enumerated.
280 ******************************************************************************/
281 const char* PrinterFactory::GetNextPrinterName
282 (
283     PRINTER_HANDLE& thePrinterHandle        //!< [in][out] handle to the printer
284 ) const
285 {
286     TRACE("PF::GetNextPrinterName()\n");
287     static FAMILY_HANDLE familyHandle;
288     nextPrinter(familyHandle, thePrinterHandle);
289     return reinterpret_cast<const char*>(thePrinterHandle);
290 } //GetNextPrinterName
291
292
293 //nextFamily
294 //! moves the family handle to the next family in the factory
295 /*!
296 updates the FAMILY_HANDLE to the next family in the factory.  After the last
297 family in the factory the FAMILY_HANDLE will be NULL.
298
299 \return
300 true - there was another family in the factory (ie FAMILY_HANDLE is not NULL)<br>
301 false - there were no more families in the factory (ie FAMILY_HANDLE is NULL)
302 ******************************************************************************/
303 bool PrinterFactory::nextFamily
304 (
305     FAMILY_HANDLE& theFamilyHandle          //!< [in][out] handle to the family
306 ) const
307 {
308     TRACE("PF::nextFamily()\n");
309     bool bMore = true;
310     const ProxyListElement* proxyList = getProxyListElement(theFamilyHandle);
311     if (proxyList == NULL)
312     {
313         TRACE("PF::nextFamily - reset to head of list\n");
314         theFamilyHandle = s_ProxyList;
315     }
316     else
317     {
318         TRACE("PF::nextFamily - next element\n");
319         theFamilyHandle = proxyList->next;
320     }
321     if (theFamilyHandle == NULL)
322     {
323         TRACE("PF::nextFamily - NULL (end of list)\n");
324         bMore = false;
325     }
326     return bMore;
327 } //nextFamily
328
329
330 //EnumDevices
331 //! moves the family handle to the next family in the factory
332 /*!
333 updates the FAMILY_HANDLE to the next family in the factory.  After the last
334 family in the factory the FAMILY_HANDLE will be NULL.
335
336 \return
337 true - there was another family in the factory (ie FAMILY_HANDLE is not NULL)<br>
338 false - there were no more families in the factory (ie FAMILY_HANDLE is NULL)
339 ******************************************************************************/
340 const PRINTER_TYPE PrinterFactory::EnumDevices
341 (
342         FAMILY_HANDLE& theFamilyHandle
343 ) const
344 {
345     TRACE("PF::EnumDevices()\n");
346     if (nextFamily(theFamilyHandle))
347     {
348         return getPrinterProxy(theFamilyHandle)->GetPrinterType();
349     }
350     else
351     {
352         return UNSUPPORTED;
353     }
354 }
355
356 //nextPrinter
357 //! determines of there is another printer in the factory
358 /*! moves the modle handle to the next model in the family.  If there are no more
359 models in the family then it moves the family handle to the next family and the
360 model handle to the start of that families model list.
361 both the family and model handels can be updated during this process.  Both will
362 be NULL if there are no more printers in this iteration of the factory.
363
364 \return
365 true - there was another printer in the factory and the family/model handle references it<br>
366 false - there were no more printers in the factory and both handles are NULL
367 ******************************************************************************/
368 bool PrinterFactory::nextPrinter
369 (
370     FAMILY_HANDLE& theFamilyHandle,         //!< [in][out] current family handle
371     MODEL_HANDLE& theModelHandle            //!< [in][out] current model handle
372 ) const
373 {
374     TRACE("PF::nextPrinter(,)\n");
375     bool bMore = true;
376     if (theFamilyHandle == NULL)   //this is the first time through
377     {
378         theFamilyHandle = StartFamilyNameEnum();
379         if (nextFamily(theFamilyHandle))
380         {
381             theModelHandle = StartModelNameEnum(theFamilyHandle);
382         }
383         else
384         {
385             bMore = false;      // no families in the list
386             goto EXIT;
387         }
388     }
389     if (GetNextModelName(theFamilyHandle, theModelHandle) == NULL) //end of model list
390     {
391         if(nextFamily(theFamilyHandle))
392         {
393             theModelHandle = StartModelNameEnum(theFamilyHandle);
394             if (GetNextModelName(theFamilyHandle, theModelHandle) == NULL)
395             {
396                 bMore = false;
397             }
398         }
399         else
400         {
401             bMore = false;
402         }
403     }
404
405 EXIT:
406     {
407         return bMore;
408     }
409 } //nextPrinter
410
411
412 //FindDevIdMatch
413 //! Find a match for a Device ID string in the factory
414 /*!
415 The device ID string can be a device ID string retrived from a printer or it
416 can be a simple model name or family name.  This will walk through each family
417 in the factory and will check to see if it is a simple family or model string
418 and if not then will check for a valid device ID string.
419
420 \return
421 A family handle based on the device ID string passed in.<br>
422 NULL if there is no match.
423 ******************************************************************************/
424 const FAMILY_HANDLE PrinterFactory::FindDevIdMatch
425 (
426     const char* szDevIdString           //!< [in] well formed device id string
427 ) const
428 {
429     TRACE("PF::FindDevIdMatch(%s)\n", szDevIdString);
430     FAMILY_HANDLE myFamilyHandle = StartFamilyNameEnum();
431
432         bool  bDevIDString = TRUE;
433     if ((!strstr(szDevIdString, "MFG:") &&
434         !strstr(szDevIdString+2, "MFG:") &&
435         !strstr(szDevIdString, "MANUFACTURER:") &&
436         !strstr(szDevIdString+2, "MANUFACTURER:")) ||
437         (!strstr(szDevIdString, "MDL:") &&
438         !strstr(szDevIdString+2, "MDL:") &&
439         !strstr(szDevIdString, "MODEL:") &&
440         !strstr(szDevIdString+2, "MODEL:")) ||
441         ((szDevIdString[0] == '\0') && (szDevIdString[1] == '\0')))
442     {
443         bDevIDString = FALSE;
444     }
445
446     while (nextFamily(myFamilyHandle))
447     {
448                 if (bDevIDString)
449                 {
450                         // check to see if a full device ID String match
451                         if (getPrinterProxy(myFamilyHandle)->DeviceMatchQuery(szDevIdString))
452                         {
453                                 break;  // found it!
454                         }
455                 }
456                 else
457                 {
458                         // check the family and see if they passed a simple model string
459                         if (getPrinterProxy(myFamilyHandle)->ModelMatchQuery(szDevIdString))
460                         {
461                                 break;  // found it!
462                         }
463                 }
464     }
465     // if we never had a match (i.e. did the break) then myFamilyHandle is NULL
466     return myFamilyHandle;
467 } //FindDevIdMatch
468
469 //GetModelBits
470 //! Get the bitwise return based on the registered family
471 /*!
472
473 \return
474 A bitwise int based on the family registered.<br
475 0 if there is no printer registered.
476 ******************************************************************************/
477 const unsigned int PrinterFactory::GetModelBits
478 (
479 ) const
480 {
481         unsigned int bits=0;
482     TRACE("PF::GetModelBits\n");
483     FAMILY_HANDLE myFamilyHandle = StartFamilyNameEnum();
484
485     while (nextFamily(myFamilyHandle))
486     {
487                 if (myFamilyHandle)
488                 {
489                         bits = bits | getPrinterProxy(myFamilyHandle)->GetModelBit();
490                 }
491     }
492     return bits;
493 } //GetModelBits
494
495 //GetModelString
496 //! Get the bitwise return based on the registered family
497 /*!
498
499 \return
500 concatnated string based on the family registered.<br
501 null string if there is no printer registered.
502 ******************************************************************************/
503 const void PrinterFactory::GetModelString
504 (
505         char* mresult,\r
506     int   mresult_length
507 ) const
508 {
509         assert(mresult);
510         mresult[0] = '\0';
511
512     TRACE("PF::GetModelString\n");
513     FAMILY_HANDLE myFamilyHandle = StartFamilyNameEnum();
514     int    i = 2;\r
515     const char   *p;
516     while (nextFamily(myFamilyHandle))
517     {\r
518         p = getPrinterProxy(myFamilyHandle)->GetFamilyName();\r
519         i += strlen(p) + 1;\r
520         if (i > mresult_length) break;
521                 HP_strcat(mresult, p);
522                 HP_strcat(mresult, " ");\r
523     }
524 } //GetModelBits
525
526
527 APDK_END_NAMESPACE