PsubUtil.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: PsubUtil.c /main/8 1996/10/31 02:09:44 cde-hp $ */
  24. /*
  25. * DtPrint/PsubUtil.c
  26. */
  27. /*
  28. * (c) Copyright 1996 Digital Equipment Corporation.
  29. * (c) Copyright 1996 Hewlett-Packard Company.
  30. * (c) Copyright 1996 International Business Machines Corp.
  31. * (c) Copyright 1996 Sun Microsystems, Inc.
  32. * (c) Copyright 1996 Novell, Inc.
  33. * (c) Copyright 1996 FUJITSU LIMITED.
  34. * (c) Copyright 1996 Hitachi.
  35. */
  36. /*
  37. * ------------------------------------------------------------------------
  38. * Include Files
  39. *
  40. */
  41. #include <ctype.h>
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include <Dt/DtNlUtils.h>
  45. #include <Dt/PsubUtilI.h>
  46. /*
  47. * ------------------------------------------------------------------------
  48. * Constant Definitions
  49. *
  50. */
  51. /*
  52. * separator between printer name and display in an X Printer Specifier
  53. */
  54. #define XPSPEC_NAME_DISP_SEP_CHAR '@'
  55. #define XPSPEC_NAME_DISP_SEP "@"
  56. #define XPSPEC_NAME_DISP_SEP_LEN 1
  57. #define XPSPEC_DISP_SCREEN_SEP "."
  58. /*
  59. * ------------------------------------------------------------------------
  60. * Static Function Declarations
  61. *
  62. */
  63. static String* BuildStringList(
  64. String list_string,
  65. int i);
  66. static XtEnum OpenXPrinterOnDisplay(
  67. String printer_name,
  68. String display_spec,
  69. Display** new_display,
  70. char** ct_printer_name);
  71. static int SpanNonWhitespace(
  72. char* string);
  73. static int SpanWhitespace(
  74. char* string);
  75. static int StringToCompoundText(
  76. Display* display,
  77. char** compound_text,
  78. const char* string);
  79. static Boolean TrimWhitespace(
  80. String s);
  81. /*
  82. * ------------------------------------------------------------------------
  83. * Name: BuildStringList
  84. *
  85. * Description:
  86. *
  87. * Build a newly allocated array of Strings by recursively parsing
  88. * whitespace delimited items out of the passed list String.
  89. *
  90. * Return value:
  91. *
  92. * The array of strings. It is the caller's responsibility to free
  93. * the returned list by calling _DtPrintFreeStringList.
  94. *
  95. */
  96. static String*
  97. BuildStringList(String list_string, int i)
  98. {
  99. String string = NULL;
  100. /*
  101. * parse the next item out of the string list
  102. */
  103. if(list_string != (String)NULL)
  104. {
  105. int length;
  106. list_string += SpanWhitespace(list_string);
  107. length = SpanNonWhitespace(list_string);
  108. if(length != 0)
  109. {
  110. string = XtCalloc(length+1, sizeof(char));
  111. strncpy(string, list_string, length);
  112. list_string += length;
  113. }
  114. }
  115. if(string == (String)NULL)
  116. {
  117. /*
  118. * end of string list; allocate the array
  119. */
  120. return (String*)XtCalloc(i+1, sizeof(String));
  121. }
  122. else
  123. {
  124. /*
  125. * recurse
  126. */
  127. String* string_list = BuildStringList(list_string, i+1);
  128. /*
  129. * set the string in the list and return
  130. */
  131. string_list[i] = string;
  132. return string_list;
  133. }
  134. }
  135. /*
  136. * ------------------------------------------------------------------------
  137. * Name: OpenXPrinterOnDisplay
  138. *
  139. * Description:
  140. *
  141. * Opens 'printer_name' on display 'display_spec'. If successful, the
  142. * passed 'new_display' is updated. This function does *not*
  143. * initialize the print context.
  144. *
  145. * The return parm 'ct_printer_name' is updated with the compound
  146. * text version of the printer name used in establishing whether the
  147. * printer is managed by the passed display. If conversion is not
  148. * possible, 'printer_name' is used as is, and the location pointed
  149. * to by 'ct_printer_name' is set to NULL. The 'ct_printer_name'
  150. * return will also be set to NULL if the function return value is
  151. * not DtPRINT_SUCCESS. If the location pointed to by
  152. * 'ct_printer_name' is updated to non-NULL, it is the caller's
  153. * responsiblity to free the memory indicated by 'ct_printer_name'
  154. * using XFree().
  155. *
  156. * The 'ct_printer_name' return is provided as a convenience for the
  157. * caller to subsequently pass to XpInitContext().
  158. *
  159. * Return value:
  160. *
  161. * DtPRINT_SUCCESS
  162. * An X printer connection was successfully opened.
  163. *
  164. * DtPRINT_NO_PRINTER
  165. * The display does not manage the indicated printer.
  166. *
  167. * DtPRINT_NOT_XP_DISPLAY
  168. * The display does not support printing.
  169. *
  170. * DtPRINT_INVALID_DISPLAY
  171. * The display could not be opened.
  172. *
  173. */
  174. static XtEnum
  175. OpenXPrinterOnDisplay(
  176. String printer_name,
  177. String display_spec,
  178. Display** new_display,
  179. char** ct_printer_name)
  180. {
  181. #if 0 && defined(PRINTING_SUPPORTED)
  182. Display* print_display;
  183. XPPrinterList printer_list;
  184. int error_base;
  185. int event_base;
  186. int printer_count;
  187. *ct_printer_name = (char*)NULL;
  188. /*
  189. * open the print display
  190. */
  191. print_display = XOpenDisplay(display_spec);
  192. if(print_display != (Display*)NULL)
  193. {
  194. if(XpQueryExtension(print_display, &event_base, &error_base))
  195. {
  196. /*
  197. * validate the printer
  198. */
  199. StringToCompoundText(print_display,
  200. ct_printer_name,
  201. printer_name);
  202. if((char*)NULL == *ct_printer_name)
  203. {
  204. printer_list =
  205. XpGetPrinterList(print_display,
  206. printer_name,
  207. &printer_count);
  208. }
  209. else
  210. {
  211. printer_list =
  212. XpGetPrinterList(print_display,
  213. *ct_printer_name,
  214. &printer_count);
  215. }
  216. if(printer_list == (XPPrinterList)NULL)
  217. {
  218. XCloseDisplay(print_display);
  219. if(*ct_printer_name)
  220. XFree(*ct_printer_name);
  221. return DtPRINT_NO_PRINTER;
  222. }
  223. else
  224. {
  225. *new_display = print_display;
  226. XpFreePrinterList(printer_list);
  227. return DtPRINT_SUCCESS;
  228. }
  229. }
  230. else
  231. {
  232. XCloseDisplay(print_display);
  233. return DtPRINT_NOT_XP_DISPLAY;
  234. }
  235. }
  236. else
  237. {
  238. return DtPRINT_INVALID_DISPLAY;
  239. }
  240. #else
  241. return DtPRINT_NO_PRINTER;
  242. #endif
  243. }
  244. /*
  245. * ------------------------------------------------------------------------
  246. * Name: SpanNonWhitespace
  247. *
  248. * Description:
  249. *
  250. * Returns the length of the initial segment of the passed string
  251. * that consists entirely of non-whitspace characters.
  252. *
  253. *
  254. */
  255. static int
  256. SpanNonWhitespace(char* string)
  257. {
  258. char* ptr;
  259. for(ptr = string;
  260. *ptr != '\0' && !DtIsspace(ptr);
  261. ptr = DtNextChar(ptr));
  262. return ptr - string;
  263. }
  264. /*
  265. * ------------------------------------------------------------------------
  266. * Name: SpanWhitespace
  267. *
  268. * Description:
  269. *
  270. * Returns the length of the initial segment of the passed string
  271. * that consists entirely of whitespace characters.
  272. *
  273. *
  274. */
  275. static int
  276. SpanWhitespace(char* string)
  277. {
  278. char* ptr;
  279. for(ptr = string;
  280. *ptr != '\0' && DtIsspace(ptr);
  281. ptr = DtNextChar(ptr));
  282. return ptr - string;
  283. }
  284. /*
  285. * ------------------------------------------------------------------------
  286. * Name: StringToCompoundText
  287. *
  288. * Description:
  289. *
  290. * Converts a string to compund text for use with Xp.
  291. *
  292. * Return Value:
  293. *
  294. * The value returned from XmbTextListToTextProperty; e.g. Success if
  295. * successful.
  296. *
  297. * The return parm compound_text will contain a pointer to the
  298. * converted text. It is the caller's responsibility to free this
  299. * string using XFree().
  300. *
  301. */
  302. static int
  303. StringToCompoundText(
  304. Display* display,
  305. char** compound_text,
  306. const char* string)
  307. {
  308. XTextProperty text_prop;
  309. int status;
  310. status = XmbTextListToTextProperty(display,
  311. (char**)&string, 1,
  312. XCompoundTextStyle,
  313. &text_prop);
  314. if(Success == status)
  315. *compound_text = (char*)text_prop.value;
  316. else
  317. *compound_text = (char*)NULL;
  318. return status;
  319. }
  320. /*
  321. * ------------------------------------------------------------------------
  322. * Name: TrimWhitespace
  323. *
  324. * Description:
  325. *
  326. * Remove leading and trailing whitespace from the passed string.
  327. * This function is multi-byte safe.
  328. *
  329. * Return value:
  330. *
  331. * True if the string was modified; False otherwise.
  332. *
  333. */
  334. static Boolean
  335. TrimWhitespace(String string)
  336. {
  337. String ptr;
  338. int i;
  339. String last_non_ws;
  340. Boolean modified = False;
  341. if((String)NULL == string)
  342. return modified;
  343. /*
  344. * find the first non-whitespace character
  345. */
  346. for(ptr = string; *ptr != '\0' && DtIsspace(ptr); ptr = DtNextChar(ptr));
  347. /*
  348. * reposition the string
  349. */
  350. if(ptr != string)
  351. {
  352. modified = True;
  353. for(i = 0; ptr[i] != '\0'; i++)
  354. string[i] = ptr[i];
  355. string[i] = '\0';
  356. }
  357. /*
  358. * find the last non-whitespace character
  359. */
  360. for(ptr = string, last_non_ws = NULL; *ptr != '\0'; ptr = DtNextChar(ptr))
  361. if(!DtIsspace(ptr))
  362. last_non_ws = ptr;
  363. /*
  364. * trim any trailing whitespace
  365. */
  366. if((String)NULL != last_non_ws)
  367. {
  368. ptr = DtNextChar(last_non_ws);
  369. if(*ptr != '\0')
  370. {
  371. modified = True;
  372. *ptr = '\0';
  373. }
  374. }
  375. return modified;
  376. }
  377. /*
  378. * ------------------------------------------------------------------------
  379. * Name: _DtPrintCreateXPrinterSpecifier
  380. *
  381. * Description:
  382. *
  383. * Concatinates the passed X printer specifier components into a
  384. * newly allocated String, inserting separators between components as
  385. * needed. All components are optional; i.e. the String parms may be
  386. * passed as NULL, and the int parms may be passed as -1.
  387. *
  388. * Separators are inserted as follows:
  389. *
  390. * * if both the 'printer_name' and 'host_name' are specified, a
  391. * "@" will be inserted between them.
  392. *
  393. * * if the 'display_num' is specified:
  394. *
  395. * - if 'spec_net' is TCP_IPC or UNSPECIFIED, a ":" will be
  396. * inserted immediately preceding it.
  397. *
  398. * - if 'spec_net' is DEC_NET, a "::" will be inserted
  399. * immediately preceding it.
  400. *
  401. * * if the 'screen_num' is specified, a "." will be inserted
  402. * immediately preceding it.
  403. *
  404. * Return value:
  405. *
  406. * A newly allocated X printer specifier. If all of the components
  407. * are omitted, an empty string ("") will be returned. It is the
  408. * responsibility of the caller to free the returned specifier by
  409. * calling XtFree.
  410. */
  411. String
  412. _DtPrintCreateXPrinterSpecifier(
  413. String printer_name,
  414. String host_name,
  415. DtPrintSpecNet spec_net,
  416. int display_num,
  417. int screen_num)
  418. {
  419. String printer_specifier;
  420. char display_string[32];
  421. char screen_string[32];
  422. int printer_name_len;
  423. int host_name_len;
  424. int specifier_len = 0;
  425. String separator;
  426. /*
  427. * printer name length
  428. */
  429. if(printer_name != (String)NULL)
  430. specifier_len += printer_name_len = strlen(printer_name);
  431. else
  432. printer_name_len = 0;
  433. /*
  434. * host name length
  435. */
  436. if(host_name != (String)NULL)
  437. specifier_len += host_name_len = strlen(host_name);
  438. else
  439. host_name_len = 0;
  440. /*
  441. * printer name / display separator length
  442. */
  443. if(printer_name_len != 0 && (host_name_len != 0 || display_num != -1))
  444. {
  445. separator = XPSPEC_NAME_DISP_SEP;
  446. specifier_len += XPSPEC_NAME_DISP_SEP_LEN;
  447. }
  448. else
  449. separator = (String)NULL;
  450. /*
  451. * display number
  452. */
  453. if(display_num == -1)
  454. display_string[0] = '\0';
  455. else
  456. specifier_len +=
  457. sprintf(display_string, "%s%d",
  458. spec_net == DtPRINT_DEC_NET ? "::" : ":",
  459. display_num);
  460. /*
  461. * screen number
  462. */
  463. if(screen_num == -1)
  464. screen_string[0] = '\0';
  465. else
  466. specifier_len +=
  467. sprintf(screen_string, "%s%d", XPSPEC_DISP_SCREEN_SEP, screen_num);
  468. /*
  469. * create and return the new printer specifier
  470. */
  471. printer_specifier = XtMalloc(specifier_len + 1);
  472. sprintf(printer_specifier,
  473. "%s%s%s%s%s",
  474. printer_name ? printer_name : "",
  475. separator ? separator : "",
  476. host_name ? host_name : "",
  477. display_string,
  478. screen_string);
  479. return printer_specifier;
  480. }
  481. /*
  482. * ------------------------------------------------------------------------
  483. * Name: _DtPrintFreeStringList
  484. *
  485. * Description:
  486. *
  487. * Frees a string list created by BuildStringList.
  488. *
  489. * Return value:
  490. *
  491. * None.
  492. *
  493. */
  494. void
  495. _DtPrintFreeStringList(
  496. String* server_list)
  497. {
  498. if(server_list)
  499. {
  500. int i;
  501. for(i = 0; server_list[i] != (String)NULL; i++)
  502. {
  503. XtFree(server_list[i]);
  504. }
  505. XtFree((char*)server_list);
  506. }
  507. }
  508. /*
  509. * ------------------------------------------------------------------------
  510. * Name: _DtPrintGetDefaultXPrinterName
  511. *
  512. * Description:
  513. *
  514. *
  515. * Return Value:
  516. *
  517. * The default printer name, or NULL if no default could be
  518. * determined. It is the responsibility of the caller to free the
  519. * memory allocated for the returned String by calling XtFree.
  520. *
  521. */
  522. String
  523. _DtPrintGetDefaultXPrinterName(
  524. Widget w)
  525. {
  526. String default_printer;
  527. if((Widget)NULL == w)
  528. {
  529. default_printer = (String)NULL;
  530. }
  531. else
  532. {
  533. XtResource res_struct;
  534. /*
  535. * initialize the resource structure
  536. */
  537. res_struct.resource_name = "xpPrinter";
  538. res_struct.resource_class = "XpPrinter";
  539. res_struct.resource_type = XmRString;
  540. res_struct.resource_size = sizeof(String);
  541. res_struct.resource_offset = 0;
  542. res_struct.default_type = XmRImmediate;
  543. res_struct.default_addr = (XtPointer)NULL;
  544. /*
  545. * pick up the printer list application resource value for the
  546. * passed widget
  547. */
  548. XtGetApplicationResources(w, (XtPointer)&default_printer,
  549. &res_struct, 1, (ArgList)NULL, 0);
  550. }
  551. /*
  552. * if the resource is undefined, search for an appropriate
  553. * environment variable
  554. */
  555. if(default_printer != (String)NULL);
  556. else if((default_printer = getenv("XPRINTER")) != (String)NULL);
  557. else if((default_printer = getenv("PDPRINTER")) != (String)NULL);
  558. else if((default_printer = getenv("LPDEST")) != (String)NULL);
  559. else if((default_printer = getenv("PRINTER")) != (String)NULL)
  560. ;
  561. /*
  562. * return a copy of the printer name
  563. */
  564. return XtNewString(default_printer);
  565. }
  566. /*
  567. * ------------------------------------------------------------------------
  568. * Name: _DtPrintGetXpPrinterList
  569. *
  570. * Description:
  571. *
  572. * Retrieves the short list of Printers from the XpPrinterList
  573. * resource, or XPPRINTERLIST environment variable.
  574. *
  575. * Return value:
  576. *
  577. * A newly allocated array of printer name Strings. It is the caller's
  578. * responsibility to free the returned array by calling
  579. * _DtPrintFreeStringList.
  580. *
  581. */
  582. String*
  583. _DtPrintGetXpPrinterList(
  584. Widget w)
  585. {
  586. XtResource res_struct;
  587. String xp_printer_list;
  588. /*
  589. * initialize the resource structure
  590. */
  591. res_struct.resource_name = "xpPrinterList";
  592. res_struct.resource_class = "XpPrinterList";
  593. res_struct.resource_type = XmRString;
  594. res_struct.resource_size = sizeof(String);
  595. res_struct.resource_offset = 0;
  596. res_struct.default_type = XmRImmediate;
  597. res_struct.default_addr = (XtPointer)NULL;
  598. /*
  599. * pick up the printer list application resource value for the passed
  600. * widget
  601. */
  602. XtGetApplicationResources(w, (XtPointer)&xp_printer_list,
  603. &res_struct, 1, (ArgList)NULL, 0);
  604. /*
  605. * if the resource is undefined, use the environment variable
  606. */
  607. if(xp_printer_list == (String)NULL)
  608. {
  609. xp_printer_list = getenv("XPRINTERLIST");
  610. }
  611. /*
  612. * build the array of printer names
  613. */
  614. if(xp_printer_list != (String)NULL)
  615. {
  616. return BuildStringList(xp_printer_list, 0);
  617. }
  618. else
  619. return (String*)NULL;
  620. }
  621. /*
  622. * ------------------------------------------------------------------------
  623. * Name: _DtPrintGetXpServerList
  624. *
  625. * Description:
  626. *
  627. * Retrieves the Xp Server list from the XpServerList resource, or if
  628. * the resource is undefined, the XPSERVERLIST environment variable
  629. * is used.
  630. *
  631. * Each server name in the return list will be of the form
  632. * "host:display". If any entry from XpServerList does not contain a
  633. * display number, a default of 0 will be used.
  634. *
  635. * Return value:
  636. *
  637. * A newly allocated array of server name Strings. It is the caller's
  638. * responsibility to free the returned array by calling
  639. * _DtPrintFreeStringList.
  640. *
  641. */
  642. String*
  643. _DtPrintGetXpServerList(
  644. Widget w)
  645. {
  646. XtResource res_struct;
  647. String xp_server_list;
  648. int error_base;
  649. int event_base;
  650. String* server_list;
  651. int i;
  652. /*
  653. * initialize the resource structure
  654. */
  655. res_struct.resource_name = "xpServerList";
  656. res_struct.resource_class = "XpServerList";
  657. res_struct.resource_type = XmRString;
  658. res_struct.resource_size = sizeof(String);
  659. res_struct.resource_offset = 0;
  660. res_struct.default_type = XmRImmediate;
  661. res_struct.default_addr = (XtPointer)NULL;
  662. /*
  663. * pick up the server list application resource value for the passed
  664. * widget
  665. */
  666. if((Widget)NULL == w)
  667. xp_server_list = (String)NULL;
  668. else
  669. XtGetApplicationResources(w, (XtPointer)&xp_server_list,
  670. &res_struct, 1, (ArgList)NULL, 0);
  671. /*
  672. * if the resource is undefined, use the environment variable value
  673. */
  674. if(xp_server_list == (String)NULL)
  675. {
  676. xp_server_list = getenv("XPSERVERLIST");
  677. }
  678. /*
  679. * convert to a list of strings
  680. */
  681. #if 0 && defined(PRINTING_SUPPORTED)
  682. if((Widget)NULL != w
  683. &&
  684. XpQueryExtension(XtDisplay(w), &event_base, &error_base))
  685. {
  686. /*
  687. * the video server supports the Xp extension, add it to the front
  688. * of the list.
  689. */
  690. server_list = BuildStringList(xp_server_list, 1);
  691. server_list[0] = XtNewString(XDisplayString(XtDisplay(w)));
  692. }
  693. else if(xp_server_list != (String)NULL)
  694. {
  695. server_list = BuildStringList(xp_server_list, 0);
  696. }
  697. else
  698. #endif /* PRINTING_SUPPORTED */
  699. server_list = (String*)NULL;
  700. /*
  701. * default the display number to ":0" if needed
  702. */
  703. for(i = 0; server_list && server_list[i]; i++)
  704. {
  705. String host_name;
  706. int display_num;
  707. /*
  708. * check to see if display number is specified
  709. */
  710. _DtPrintParseXDisplaySpecifier(server_list[i],
  711. &host_name,
  712. (DtPrintSpecNet*)NULL,
  713. &display_num,
  714. (int*)NULL);
  715. if(display_num == -1)
  716. {
  717. /*
  718. * display number not specified; default to ":0"
  719. */
  720. XtFree(server_list[i]);
  721. server_list[i] =
  722. _DtPrintCreateXPrinterSpecifier((String)NULL, host_name,
  723. DtPRINT_TCP_IPC, 0, -1);
  724. }
  725. XtFree(host_name);
  726. }
  727. /*
  728. * return
  729. */
  730. return server_list;
  731. }
  732. /*
  733. * ------------------------------------------------------------------------
  734. * Name: _DtPrintParseXDisplaySpecifier
  735. *
  736. * Description:
  737. *
  738. * Parse the host name and the display and screen numbers from a
  739. * conventional X Display Specifier (e.g. as in the DISPLAY env var).
  740. *
  741. * This function returns the component values into the locations
  742. * pointed to by the host_name, display_num, and screen_num
  743. * parameters. If any component is not desired, the corresponding
  744. * parm may be set to NULL. If a non-NULL host_name is passed, it is
  745. * the responsibility of the caller to free the newly allocated
  746. * String set in this parm by calling XtFree().
  747. *
  748. * If the hostname component is missing from the passed display spec,
  749. * an empty string is returned. If the display spec is NULL, NULL is
  750. * returned. (-1) will be returned for the display or screen number
  751. * if the display spec is NULL or if the display or screen component
  752. * is missing from the spec.
  753. *
  754. * Return value:
  755. *
  756. * None.
  757. *
  758. */
  759. void
  760. _DtPrintParseXDisplaySpecifier(
  761. const String display_spec,
  762. String* host_name,
  763. DtPrintSpecNet* spec_net,
  764. int* display_num,
  765. int* screen_num)
  766. {
  767. char* ptr;
  768. if(display_spec == (String)NULL)
  769. {
  770. /*
  771. * not much to do with a NULL display spec
  772. */
  773. if(host_name) *host_name = (String)NULL;
  774. if(spec_net) *spec_net = DtPRINT_NET_UNSPECIFIED;
  775. if(display_num) *display_num = -1;
  776. if(screen_num) *screen_num = -1;
  777. return;
  778. }
  779. /*
  780. * find the start of the display number in the display spec
  781. */
  782. ptr = DtStrchr(display_spec, ':');
  783. if(ptr == (char*)NULL)
  784. {
  785. /*
  786. * not found, return -1 for display and screen
  787. */
  788. if(spec_net) *spec_net = DtPRINT_NET_UNSPECIFIED;
  789. if(display_num) *display_num = -1;
  790. if(screen_num) *screen_num = -1;
  791. /*
  792. * return the host name as a copy of the display spec
  793. */
  794. if(host_name) *host_name = XtNewString(display_spec);
  795. }
  796. else
  797. {
  798. int num;
  799. /*
  800. * skip over the ':', determine if this is a DECnet specifier,
  801. * and pick up the display num if specified
  802. */
  803. ++ptr;
  804. if(*ptr == '\0')
  805. {
  806. if(spec_net) *spec_net = DtPRINT_NET_UNSPECIFIED;
  807. num = -1;
  808. }
  809. else
  810. {
  811. if(*ptr == ':')
  812. {
  813. if(spec_net) *spec_net = DtPRINT_DEC_NET;
  814. ++ptr;
  815. }
  816. else
  817. {
  818. if(spec_net) *spec_net = DtPRINT_TCP_IPC;
  819. }
  820. if(*ptr == '\0')
  821. num = -1;
  822. else
  823. num = (int)strtol(ptr, &ptr, 10);
  824. }
  825. if(display_num) *display_num = num;
  826. if(screen_num)
  827. {
  828. if(num == -1)
  829. {
  830. *screen_num = -1;
  831. }
  832. else
  833. {
  834. /*
  835. * parse out the screen number
  836. */
  837. if(*ptr == '.' && *(ptr+1) != '\0')
  838. {
  839. ++ptr;
  840. num = (int)strtol(ptr, &ptr, 10);
  841. if(screen_num) *screen_num = num;
  842. }
  843. else
  844. {
  845. /*
  846. * not found, return -1 for screen
  847. */
  848. *screen_num = -1;
  849. }
  850. }
  851. }
  852. if(host_name)
  853. {
  854. /*
  855. * allocate a new string containing just the host name
  856. */
  857. int host_name_len = DtStrcspn(display_spec, ":");
  858. *host_name = XtMalloc(host_name_len+1);
  859. strncpy(*host_name, display_spec, host_name_len);
  860. (*host_name)[host_name_len] = '\0';
  861. }
  862. }
  863. }
  864. /*
  865. * ------------------------------------------------------------------------
  866. * Name: _DtPrintParseXPrinterSpecifier
  867. *
  868. * Description:
  869. *
  870. * Parse the printer name and display specifier components out of an
  871. * X Printer Specifier. This function returns these components as
  872. * newly allocated Strings into the locations pointed to by
  873. * printer_name and display_spec. It is the responsibility of the
  874. * caller to free the Strings by calling XtFree().
  875. *
  876. * The printer_name or display_spec parameters may be passed as NULL
  877. * if that component of the specifier is not desired.
  878. *
  879. * If the printer specifier is NULL, the locations pointed to
  880. * by the printer_name and display_spec will be set to NULL.
  881. *
  882. * If either portion of the specifier is missing, a newly allocated
  883. * empty string will be returned to printer_name or display_spec.
  884. *
  885. * Return value:
  886. *
  887. * None.
  888. *
  889. */
  890. void
  891. _DtPrintParseXPrinterSpecifier(
  892. const String specifier,
  893. String* printer_name,
  894. String* display_spec)
  895. {
  896. if(specifier == (String)NULL)
  897. {
  898. if(printer_name) *printer_name = (String)NULL;
  899. if(display_spec) *display_spec = (String)NULL;
  900. }
  901. else
  902. {
  903. String delim_ptr;
  904. /*
  905. * determine the offset of the printer name / display name delimiter
  906. * ('@') within the X Printer Specifier
  907. */
  908. delim_ptr = DtStrchr(specifier, XPSPEC_NAME_DISP_SEP_CHAR);
  909. if(delim_ptr == (String)NULL)
  910. {
  911. /*
  912. * no delimiter found; specifier consists of printer name only
  913. */
  914. if(printer_name) *printer_name = XtNewString(specifier);
  915. if(display_spec) *display_spec = XtNewString("");
  916. }
  917. else
  918. {
  919. /*
  920. * copy the printer name portion from the specifier
  921. */
  922. if(printer_name)
  923. {
  924. int printer_name_len = delim_ptr - specifier;
  925. *printer_name = (String)XtMalloc(printer_name_len + 1);
  926. strncpy(*printer_name, specifier, printer_name_len);
  927. (*printer_name)[printer_name_len] = '\0';
  928. }
  929. /*
  930. * copy the display name portion from the specifier
  931. */
  932. if(display_spec) *display_spec = XtNewString(delim_ptr+1);
  933. }
  934. }
  935. }
  936. /*
  937. * ------------------------------------------------------------------------
  938. * Name: _DtPrintVerifyXPrinter
  939. *
  940. * Description:
  941. *
  942. * Determines if an X printer specifier is valid by establishing a
  943. * connection to the printer, up to and including initializing a
  944. * print context.
  945. *
  946. * If the passed printer specifier is NULL, a default will be
  947. * used. If the passed specifier is incomplete, this function will
  948. * attempt to determine a fully qualified specifier based on the Xp
  949. * server list environment variable or XRM resource. If the specifier
  950. * does not include a display number, ":0" will be used.
  951. *
  952. * If this function is successful, the 'new_display' return parameter
  953. * will be set to the Display of the verified printer connection. If
  954. * the passed 'printer_spec' was used as passed to establish the
  955. * connection, the 'new_printer' parm will be set to NULL. If a
  956. * default or fully-qualified version of the printer specifier was
  957. * generated, the generated specifier will be returned via the
  958. * 'new_printer' parameter. It is the responsibility of the caller to
  959. * free the generated String by calling XtFree. 'new_printer_spec'
  960. * may be set whether or not _DtPrintVerifyXPrinter successfully
  961. * opens an X printer connection.
  962. *
  963. * Return value:
  964. *
  965. * DtPRINT_SUCCESS
  966. * An X printer connection was successfully opened.
  967. *
  968. * DtPRINT_PRINTER_MISSING
  969. * The passed or default printer spec does not include a printer
  970. * name component.
  971. *
  972. * DtPRINT_NO_DEFAULT
  973. * The passed printer spec was NULL, and no default printer could
  974. * be determined.
  975. *
  976. * DtPRINT_NO_DEFAULT_DISPLAY
  977. * The passed printer spec or default did not include a display
  978. * specifier, and no suitable display could be found within the
  979. * Xp server list.
  980. *
  981. * DtPRINT_NO_PRINTER
  982. * The display indicated in the passed printer spec or default
  983. * does not manage the indicated printer.
  984. *
  985. * DtPRINT_NOT_XP_DISPLAY
  986. * The display indicated in the passed printer spec or default
  987. * does not support printing.
  988. *
  989. * DtPRINT_INVALID_DISPLAY
  990. * The display indicated in the passed printer spec or default
  991. * could not be opened.
  992. *
  993. */
  994. XtEnum
  995. _DtPrintVerifyXPrinter(
  996. Widget w,
  997. String printer_spec,
  998. String* new_printer_spec,
  999. Display** new_display
  1000. #if 0 && defined(PRINTING_SUPPORTED)
  1001. ,XPContext* new_context
  1002. #endif /* PRINTING_SUPPORTED */
  1003. )
  1004. {
  1005. String default_printer;
  1006. String printer_name;
  1007. String display_spec;
  1008. XtEnum status;
  1009. Display* print_display;
  1010. char* ct_printer_name;
  1011. String trimmed_spec;
  1012. /*
  1013. * initialize the printer spec return parm
  1014. */
  1015. *new_printer_spec = (String)NULL;
  1016. /*
  1017. * determine a default printer if the passed printer spec is NULL
  1018. */
  1019. if(printer_spec == (String)NULL)
  1020. {
  1021. default_printer = _DtPrintGetDefaultXPrinterName(w);
  1022. if(default_printer == (String)NULL)
  1023. return DtPRINT_NO_DEFAULT;
  1024. else
  1025. printer_spec = default_printer;
  1026. }
  1027. else
  1028. default_printer = (String)NULL;
  1029. /*
  1030. * trim whitespace from the printer spec if needed
  1031. */
  1032. trimmed_spec = XtNewString(printer_spec);
  1033. if(TrimWhitespace(trimmed_spec))
  1034. {
  1035. printer_spec = trimmed_spec;
  1036. }
  1037. else
  1038. {
  1039. XtFree(trimmed_spec);
  1040. trimmed_spec = (String)NULL;
  1041. }
  1042. /*
  1043. * break the printer specifier into its printer name and display
  1044. * specifier components
  1045. */
  1046. _DtPrintParseXPrinterSpecifier(printer_spec,
  1047. &printer_name,
  1048. &display_spec);
  1049. if(*printer_name == '\0')
  1050. {
  1051. /*
  1052. * printer name is missing
  1053. */
  1054. status = DtPRINT_PRINTER_MISSING;
  1055. }
  1056. else
  1057. {
  1058. /*
  1059. * if the display spec is empty, search the server list for a
  1060. * suitable display
  1061. */
  1062. if(*display_spec == '\0')
  1063. {
  1064. String* server_list;
  1065. int i;
  1066. /*
  1067. * find a server in the server list that manages the printer
  1068. */
  1069. status = DtPRINT_NO_DEFAULT_DISPLAY;
  1070. if((server_list = _DtPrintGetXpServerList(w)) != (String*)NULL)
  1071. {
  1072. for(i = 0; server_list[i] != (String)NULL; i++)
  1073. {
  1074. if(OpenXPrinterOnDisplay(printer_name,
  1075. server_list[i],
  1076. &print_display,
  1077. &ct_printer_name)
  1078. == DtPRINT_SUCCESS)
  1079. {
  1080. status = DtPRINT_SUCCESS;
  1081. *new_printer_spec =
  1082. _DtPrintCreateXPrinterSpecifier(
  1083. printer_name,
  1084. server_list[i],
  1085. DtPRINT_NET_UNSPECIFIED,
  1086. -1, -1);
  1087. break;
  1088. }
  1089. }
  1090. _DtPrintFreeStringList(server_list);
  1091. }
  1092. }
  1093. else
  1094. {
  1095. String host_name;
  1096. int display_num;
  1097. /*
  1098. * check to see if display number is specified
  1099. */
  1100. _DtPrintParseXDisplaySpecifier(display_spec,
  1101. &host_name,
  1102. (DtPrintSpecNet*)NULL,
  1103. &display_num,
  1104. (int*)NULL);
  1105. if(display_num == -1)
  1106. {
  1107. String new_display_spec;
  1108. /*
  1109. * display number not specified; default to ":0"
  1110. */
  1111. new_display_spec =
  1112. _DtPrintCreateXPrinterSpecifier((String)NULL, host_name,
  1113. DtPRINT_TCP_IPC, 0, -1);
  1114. /*
  1115. * create new printer name for return, even if
  1116. * OpenXPrinterOnDisplay is unsuccessful
  1117. */
  1118. *new_printer_spec =
  1119. _DtPrintCreateXPrinterSpecifier(printer_name,
  1120. new_display_spec,
  1121. DtPRINT_NET_UNSPECIFIED,
  1122. -1, -1);
  1123. /*
  1124. * use the new display spec
  1125. */
  1126. XtFree(display_spec);
  1127. display_spec = new_display_spec;
  1128. }
  1129. XtFree(host_name);
  1130. /*
  1131. * open the print display
  1132. */
  1133. status = OpenXPrinterOnDisplay(printer_name,
  1134. display_spec,
  1135. &print_display,
  1136. &ct_printer_name);
  1137. }
  1138. }
  1139. if(status == DtPRINT_SUCCESS)
  1140. {
  1141. /*
  1142. * initialize the print context
  1143. */
  1144. #if 0 && defined(PRINTING_SUPPORTED)
  1145. if((char*)NULL != ct_printer_name)
  1146. {
  1147. *new_context = XpCreateContext(print_display, ct_printer_name);
  1148. XFree(ct_printer_name);
  1149. }
  1150. else
  1151. *new_context = XpCreateContext(print_display, printer_name);
  1152. XpSetContext(print_display, *new_context);
  1153. #endif /* PRINTING_SUPPORTED */
  1154. /*
  1155. * update the display return parm
  1156. */
  1157. *new_display = print_display;
  1158. }
  1159. /*
  1160. * check to see if the trimmed spec was used
  1161. */
  1162. if(trimmed_spec != (String)NULL)
  1163. {
  1164. if(*new_printer_spec == (String)NULL)
  1165. {
  1166. /*
  1167. * the trimmed spec was used as is; return it as the new
  1168. * printer specifier
  1169. */
  1170. *new_printer_spec = trimmed_spec;
  1171. }
  1172. else
  1173. {
  1174. /*
  1175. * a modified version of the trimmed spec was used
  1176. */
  1177. XtFree(trimmed_spec);
  1178. }
  1179. XtFree(default_printer);
  1180. }
  1181. else if(default_printer != (String)NULL)
  1182. {
  1183. /*
  1184. * check to see if the default printer was used without
  1185. * modification
  1186. */
  1187. if(*new_printer_spec == (String)NULL)
  1188. {
  1189. /*
  1190. * the default printer was used as is; return it as the new
  1191. * printer specifier
  1192. */
  1193. *new_printer_spec = default_printer;
  1194. }
  1195. else
  1196. {
  1197. /*
  1198. * a modified version of the default printer was used
  1199. */
  1200. XtFree(default_printer);
  1201. }
  1202. }
  1203. /*
  1204. * clean up and return
  1205. */
  1206. XtFree(printer_name);
  1207. XtFree(display_spec);
  1208. return status;
  1209. }