~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/toolkit/components/printing/content/printdialog.js

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
# ***** BEGIN LICENSE BLOCK *****
 
3
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4
#
 
5
# The contents of this file are subject to the Mozilla Public License Version
 
6
# 1.1 (the "License"); you may not use this file except in compliance with
 
7
# the License. You may obtain a copy of the License at
 
8
# http://www.mozilla.org/MPL/
 
9
#
 
10
# Software distributed under the License is distributed on an "AS IS" basis,
 
11
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
# for the specific language governing rights and limitations under the
 
13
# License.
 
14
#
 
15
# The Original Code is mozilla.org printing front-end.
 
16
#
 
17
# The Initial Developer of the Original Code is
 
18
# Netscape Communications Corporation.
 
19
# Portions created by the Initial Developer are Copyright (C) 2002
 
20
# the Initial Developer. All Rights Reserved.
 
21
#
 
22
# Contributor(s): 
 
23
#   Masaki Katakai <katakai@japan.sun.com>
 
24
#   Jessica Blanco <jblanco@us.ibm.com>
 
25
#   Asko Tontti <atontti@cc.hut.fi>
 
26
#   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
 
27
#
 
28
# Alternatively, the contents of this file may be used under the terms of
 
29
# either the GNU General Public License Version 2 or later (the "GPL"), or 
 
30
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
31
# in which case the provisions of the GPL or the LGPL are applicable instead
 
32
# of those above. If you wish to allow use of your version of this file only
 
33
# under the terms of either the GPL or the LGPL, and not to allow others to
 
34
# use your version of this file under the terms of the NPL, indicate your
 
35
# decision by deleting the provisions above and replace them with the notice
 
36
# and other provisions required by the GPL or the LGPL. If you do not delete
 
37
# the provisions above, a recipient may use your version of this file under
 
38
# the terms of any one of the NPL, the GPL or the LGPL.
 
39
#
 
40
# ***** END LICENSE BLOCK *****
 
41
 
 
42
var dialog;
 
43
var printService       = null;
 
44
var printOptions       = null;
 
45
var gOriginalNumCopies = 1;
 
46
 
 
47
var paramBlock;
 
48
var gPrintSettings     = null;
 
49
var gWebBrowserPrint   = null;
 
50
var default_file       = "mozilla.ps";
 
51
var gPrintSetInterface = Components.interfaces.nsIPrintSettings;
 
52
var doDebug            = false;
 
53
var gFileFromPicker    = "";
 
54
 
 
55
//---------------------------------------------------
 
56
function initDialog()
 
57
{
 
58
  dialog = new Object;
 
59
 
 
60
  dialog.propertiesButton = document.getElementById("properties");
 
61
 
 
62
  dialog.destGroup       = document.getElementById("destGroup");
 
63
  dialog.fileRadio       = document.getElementById("fileRadio");
 
64
  dialog.printerRadio    = document.getElementById("printerRadio");
 
65
 
 
66
  dialog.printrangeGroup = document.getElementById("printrangeGroup");
 
67
  dialog.allpagesRadio   = document.getElementById("allpagesRadio");
 
68
  dialog.rangeRadio      = document.getElementById("rangeRadio");
 
69
  dialog.selectionRadio  = document.getElementById("selectionRadio");
 
70
  dialog.frompageInput   = document.getElementById("frompageInput");
 
71
  dialog.frompageLabel   = document.getElementById("frompageLabel");
 
72
  dialog.topageInput     = document.getElementById("topageInput");
 
73
  dialog.topageLabel     = document.getElementById("topageLabel");
 
74
 
 
75
  dialog.numCopiesInput  = document.getElementById("numCopiesInput");  
 
76
 
 
77
  dialog.printframeGroup      = document.getElementById("printframeGroup");
 
78
  dialog.aslaidoutRadio       = document.getElementById("aslaidoutRadio");
 
79
  dialog.selectedframeRadio   = document.getElementById("selectedframeRadio");
 
80
  dialog.eachframesepRadio    = document.getElementById("eachframesepRadio");
 
81
  dialog.printframeGroupLabel = document.getElementById("printframeGroupLabel");
 
82
 
 
83
  dialog.fileInput       = document.getElementById("fileInput");
 
84
  dialog.fileLabel       = document.getElementById("fileLabel");
 
85
  dialog.printerLabel    = document.getElementById("printerLabel");
 
86
  dialog.chooseButton    = document.getElementById("chooseFile");
 
87
  dialog.printerList     = document.getElementById("printerList");
 
88
 
 
89
  dialog.printButton     = document.documentElement.getButton("accept");
 
90
 
 
91
  // <data> elements
 
92
  dialog.printName       = document.getElementById("printButton");
 
93
  dialog.fpDialog        = document.getElementById("fpDialog");
 
94
 
 
95
  dialog.enabled         = false;
 
96
}
 
97
 
 
98
//---------------------------------------------------
 
99
function checkInteger(element)
 
100
{
 
101
  var value = element.value;
 
102
  if (value && value.length > 0) {
 
103
    value = value.replace(/[^0-9]/g,"");
 
104
    if (!value) value = "";
 
105
    element.value = value;
 
106
  }
 
107
  if (!value || value < 1 || value > 999)
 
108
    dialog.printButton.setAttribute("disabled","true");
 
109
  else
 
110
    dialog.printButton.removeAttribute("disabled");
 
111
}
 
112
 
 
113
//---------------------------------------------------
 
114
function stripTrailingWhitespace(element)
 
115
{
 
116
  var value = element.value;
 
117
  value = value.replace(/\s+$/,"");
 
118
  element.value = value;
 
119
}
 
120
 
 
121
//---------------------------------------------------
 
122
function doEnablePrintToFile(value)
 
123
{
 
124
  if (value) {
 
125
    dialog.fileLabel.removeAttribute("disabled");
 
126
    dialog.fileInput.removeAttribute("disabled");
 
127
    dialog.chooseButton.removeAttribute("disabled");
 
128
  } else {
 
129
    dialog.fileLabel.setAttribute("disabled","true");
 
130
    dialog.fileInput.setAttribute("disabled","true");
 
131
    dialog.chooseButton.setAttribute("disabled","true");
 
132
  }
 
133
}
 
134
 
 
135
//---------------------------------------------------
 
136
function listElement(aListElement)
 
137
  {
 
138
    this.listElement = aListElement;
 
139
  }
 
140
 
 
141
listElement.prototype =
 
142
  {
 
143
    clearList:
 
144
      function ()
 
145
        {
 
146
          // remove the menupopup node child of the menulist.
 
147
          this.listElement.removeChild(this.listElement.firstChild);
 
148
        },
 
149
 
 
150
    appendPrinterNames: 
 
151
      function (aDataObject) 
 
152
        { 
 
153
          var popupNode = document.createElement("menupopup"); 
 
154
          var strDefaultPrinterName = "";
 
155
          var printerName;
 
156
 
 
157
          // build popup menu from printer names
 
158
          while (aDataObject.hasMoreElements()) {
 
159
            printerName = aDataObject.getNext();
 
160
            printerName = printerName.QueryInterface(Components.interfaces.nsISupportsString);
 
161
            var printerNameStr = printerName.toString();
 
162
            if (strDefaultPrinterName == "")
 
163
               strDefaultPrinterName = printerNameStr;
 
164
            var itemNode = document.createElement("menuitem");
 
165
            itemNode.setAttribute("value", printerNameStr);
 
166
            itemNode.setAttribute("label", printerNameStr);
 
167
            popupNode.appendChild(itemNode);
 
168
          }
 
169
          if (strDefaultPrinterName != "") {
 
170
            this.listElement.removeAttribute("disabled");
 
171
          } else {
 
172
            var stringBundle = srGetStrBundle("chrome://global/locale/printing.properties");
 
173
            this.listElement.setAttribute("value", strDefaultPrinterName);
 
174
            this.listElement.setAttribute("label", stringBundle.GetStringFromName("noprinter"));
 
175
 
 
176
            // disable dialog
 
177
            this.listElement.setAttribute("disabled", "true");
 
178
            dialog.destGroup.setAttribute("disabled","true");
 
179
            dialog.printerRadio.setAttribute("disabled","true");
 
180
            dialog.printerLabel.setAttribute("disabled","true");
 
181
            dialog.propertiesButton.setAttribute("disabled","true");
 
182
            dialog.fileRadio.setAttribute("disabled","true");
 
183
            dialog.printButton.setAttribute("disabled","true");
 
184
            doEnablePrintToFile(false);
 
185
          }
 
186
 
 
187
          this.listElement.appendChild(popupNode); 
 
188
          return strDefaultPrinterName;
 
189
        } 
 
190
  };
 
191
 
 
192
//---------------------------------------------------
 
193
function getPrinters()
 
194
{
 
195
  var printerEnumerator = printOptions.availablePrinters();
 
196
 
 
197
  var selectElement = new listElement(dialog.printerList);
 
198
  selectElement.clearList();
 
199
  var strDefaultPrinterName = selectElement.appendPrinterNames(printerEnumerator);
 
200
 
 
201
  selectElement.listElement.value = strDefaultPrinterName;
 
202
 
 
203
  // make sure we load the prefs for the initially selected printer
 
204
  setPrinterDefaultsForSelectedPrinter();
 
205
}
 
206
 
 
207
 
 
208
//---------------------------------------------------
 
209
// update gPrintSettings with the defaults for the selected printer
 
210
function setPrinterDefaultsForSelectedPrinter()
 
211
{
 
212
  gPrintSettings.printerName = dialog.printerList.value;
 
213
  
 
214
  // First get any defaults from the printer 
 
215
  printService.initPrintSettingsFromPrinter(gPrintSettings.printerName, gPrintSettings);
 
216
  
 
217
  // now augment them with any values from last time
 
218
  printService.initPrintSettingsFromPrefs(gPrintSettings, true, gPrintSetInterface.kInitSaveAll);
 
219
  
 
220
  if (doDebug) {
 
221
    dump("setPrinterDefaultsForSelectedPrinter: printerName='"+gPrintSettings.printerName+"', paperName='"+gPrintSettings.paperName+"'\n");
 
222
  }
 
223
}
 
224
 
 
225
//---------------------------------------------------
 
226
function displayPropertiesDialog()
 
227
{
 
228
  gPrintSettings.numCopies = dialog.numCopiesInput.value;
 
229
  try {
 
230
    var printingPromptService = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
 
231
                                                 .getService(Components.interfaces.nsIPrintingPromptService);
 
232
    if (printingPromptService) {
 
233
      printingPromptService.showPrinterProperties(null, dialog.printerList.value, gPrintSettings);
 
234
      dialog.numCopiesInput.value = gPrintSettings.numCopies;
 
235
    }
 
236
  } catch(e) {
 
237
    dump("problems getting printingPromptService\n");
 
238
  }
 
239
}
 
240
 
 
241
//---------------------------------------------------
 
242
function doPrintRange(inx)
 
243
{
 
244
  if (inx == 1) {
 
245
    dialog.frompageInput.removeAttribute("disabled");
 
246
    dialog.frompageLabel.removeAttribute("disabled");
 
247
    dialog.topageInput.removeAttribute("disabled");
 
248
    dialog.topageLabel.removeAttribute("disabled");
 
249
  } else {
 
250
    dialog.frompageInput.setAttribute("disabled","true");
 
251
    dialog.frompageLabel.setAttribute("disabled","true");
 
252
    dialog.topageInput.setAttribute("disabled","true");
 
253
    dialog.topageLabel.setAttribute("disabled","true");
 
254
  }
 
255
}
 
256
 
 
257
//---------------------------------------------------
 
258
function loadDialog()
 
259
{
 
260
  var print_copies        = 1;
 
261
  var print_file          = default_file;
 
262
  var print_selection_radio_enabled = false;
 
263
  var print_frametype     = gPrintSetInterface.kSelectedFrame;
 
264
  var print_howToEnableUI = gPrintSetInterface.kFrameEnableNone;
 
265
  var print_tofile        = "";
 
266
 
 
267
  try {
 
268
    printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"];
 
269
    if (printService) {
 
270
      printService = printService.getService();
 
271
      if (printService) {
 
272
        printService = printService.QueryInterface(Components.interfaces.nsIPrintSettingsService);
 
273
        printOptions = printService.QueryInterface(Components.interfaces.nsIPrintOptions);
 
274
      }
 
275
    }
 
276
  } catch(e) {}
 
277
 
 
278
  // Note: getPrinters sets up the PrintToFile radio buttons and initalises gPrintSettings
 
279
  getPrinters();
 
280
 
 
281
  if (gPrintSettings) {
 
282
    print_tofile        = gPrintSettings.printToFile;
 
283
    gOriginalNumCopies  = gPrintSettings.numCopies;
 
284
 
 
285
    print_copies        = gPrintSettings.numCopies;
 
286
    print_file          = gPrintSettings.toFileName;
 
287
    print_frametype     = gPrintSettings.printFrameType;
 
288
    print_howToEnableUI = gPrintSettings.howToEnableFrameUI;
 
289
    print_selection_radio_enabled = gPrintSettings.GetPrintOptions(gPrintSetInterface.kEnableSelectionRB);
 
290
  }
 
291
 
 
292
  if (print_tofile) {
 
293
    dialog.destGroup.selectedItem = dialog.fileRadio;
 
294
    doEnablePrintToFile(true);
 
295
  } else {
 
296
    dialog.destGroup.selectedItem = dialog.printerRadio;
 
297
    doEnablePrintToFile(false);
 
298
  }
 
299
 
 
300
  if (doDebug) {
 
301
    dump("loadDialog*********************************************\n");
 
302
    dump("toFileName              ["+print_file+"]\n");
 
303
    dump("print_tofile            "+print_tofile+"\n");
 
304
    dump("print_frame             "+print_frametype+"\n");
 
305
    dump("print_howToEnableUI     "+print_howToEnableUI+"\n");
 
306
    dump("selection_radio_enabled "+print_selection_radio_enabled+"\n");
 
307
  }
 
308
 
 
309
  if (print_file == "") {
 
310
    print_file = default_file;
 
311
  }
 
312
 
 
313
  dialog.printrangeGroup.selectedItem = dialog.allpagesRadio;
 
314
  if (print_selection_radio_enabled) {
 
315
    dialog.selectionRadio.removeAttribute("disabled");
 
316
  } else {
 
317
    dialog.selectionRadio.setAttribute("disabled","true");
 
318
  }
 
319
  doPrintRange(dialog.rangeRadio.selected);
 
320
  dialog.frompageInput.value  = 1;
 
321
  dialog.topageInput.value    = 1;
 
322
  dialog.numCopiesInput.value = print_copies;
 
323
 
 
324
  dialog.fileInput.value   = print_file;
 
325
 
 
326
  if (gPrintSettings.toFileName != "") {
 
327
    dialog.fileInput.value = gPrintSettings.toFileName;
 
328
  }
 
329
 
 
330
  if (doDebug) {
 
331
    dump("print_howToEnableUI: "+print_howToEnableUI+"\n");
 
332
  }
 
333
 
 
334
  // print frame
 
335
  if (print_howToEnableUI == gPrintSetInterface.kFrameEnableAll) {
 
336
    dialog.aslaidoutRadio.removeAttribute("disabled");
 
337
 
 
338
    dialog.selectedframeRadio.removeAttribute("disabled");
 
339
    dialog.eachframesepRadio.removeAttribute("disabled");
 
340
    dialog.printframeGroupLabel.removeAttribute("disabled");
 
341
 
 
342
    // initialize radio group
 
343
    dialog.printframeGroup.selectedItem = dialog.selectedframeRadio;
 
344
 
 
345
  } else if (print_howToEnableUI == gPrintSetInterface.kFrameEnableAsIsAndEach) {
 
346
    dialog.aslaidoutRadio.removeAttribute("disabled");       //enable
 
347
 
 
348
    dialog.selectedframeRadio.setAttribute("disabled","true"); // disable
 
349
    dialog.eachframesepRadio.removeAttribute("disabled");       // enable
 
350
    dialog.printframeGroupLabel.removeAttribute("disabled");    // enable
 
351
 
 
352
    // initialize
 
353
    dialog.printframeGroup.selectedItem = dialog.eachframesepRadio;
 
354
 
 
355
  } else {
 
356
    dialog.aslaidoutRadio.setAttribute("disabled","true");
 
357
    dialog.selectedframeRadio.setAttribute("disabled","true");
 
358
    dialog.eachframesepRadio.setAttribute("disabled","true");
 
359
    dialog.printframeGroupLabel.setAttribute("disabled","true");
 
360
  }
 
361
 
 
362
  dialog.printButton.label = dialog.printName.getAttribute("label");
 
363
}
 
364
 
 
365
//---------------------------------------------------
 
366
function onLoad()
 
367
{
 
368
  // Init dialog.
 
369
  initDialog();
 
370
 
 
371
  // param[0]: nsIPrintSettings object
 
372
  // param[1]: container for return value (1 = print, 0 = cancel)
 
373
 
 
374
  gPrintSettings   = window.arguments[0].QueryInterface(gPrintSetInterface);
 
375
  gWebBrowserPrint = window.arguments[1].QueryInterface(Components.interfaces.nsIWebBrowserPrint);
 
376
  paramBlock       = window.arguments[2].QueryInterface(Components.interfaces.nsIDialogParamBlock);
 
377
 
 
378
  // default return value is "cancel"
 
379
  paramBlock.SetInt(0, 0);
 
380
 
 
381
  loadDialog();
 
382
}
 
383
 
 
384
//---------------------------------------------------
 
385
function onAccept()
 
386
{
 
387
 
 
388
  if (gPrintSettings) {
 
389
    var print_howToEnableUI = gPrintSetInterface.kFrameEnableNone;
 
390
    var stringBundle = srGetStrBundle("chrome://global/locale/printing.properties");
 
391
    var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
 
392
                        .getService(Components.interfaces.nsIPromptService);
 
393
 
 
394
    if (dialog.fileRadio.selected && dialog.fileInput.value == "") {
 
395
      var titleText = stringBundle.GetStringFromName("noPrintFilename.title");
 
396
      var alertText = stringBundle.GetStringFromName("noPrintFilename.alert");
 
397
      promptService.alert(this.window, titleText, alertText);
 
398
      return false;
 
399
    }
 
400
 
 
401
    // save these out so they can be picked up by the device spec
 
402
    gPrintSettings.printToFile = dialog.fileRadio.selected;
 
403
    print_howToEnableUI        = gPrintSettings.howToEnableFrameUI;
 
404
 
 
405
    // save these out so they can be picked up by the device spec
 
406
    gPrintSettings.toFileName   = dialog.fileInput.value;
 
407
    gPrintSettings.printerName  = dialog.printerList.value;
 
408
 
 
409
    if (gPrintSettings.printToFile) {
 
410
      if (gPrintSettings.toFileName == "")
 
411
        return false;
 
412
      var sfile = Components.classes["@mozilla.org/file/local;1"]
 
413
                  .createInstance(Components.interfaces.nsILocalFile);
 
414
      sfile.initWithPath(gPrintSettings.toFileName);
 
415
      if (sfile.exists() &&
 
416
        gPrintSettings.toFileName != gFileFromPicker) {
 
417
        var desc = stringBundle.formatStringFromName("fileConfirm.exists",
 
418
                                                     [gPrintSettings.toFileName],
 
419
                                                     1);
 
420
        if (!promptService.confirm(this.window, null, desc)) {
 
421
          return false;
 
422
        }
 
423
      }
 
424
    }
 
425
 
 
426
    if (dialog.allpagesRadio.selected) {
 
427
      gPrintSettings.printRange = gPrintSetInterface.kRangeAllPages;
 
428
    } else if (dialog.rangeRadio.selected) {
 
429
      gPrintSettings.printRange = gPrintSetInterface.kRangeSpecifiedPageRange;
 
430
    } else if (dialog.selectionRadio.selected) {
 
431
      gPrintSettings.printRange = gPrintSetInterface.kRangeSelection;
 
432
    }
 
433
    gPrintSettings.startPageRange = dialog.frompageInput.value;
 
434
    gPrintSettings.endPageRange   = dialog.topageInput.value;
 
435
    gPrintSettings.numCopies      = dialog.numCopiesInput.value;
 
436
 
 
437
    var frametype = gPrintSetInterface.kNoFrames;
 
438
    if (print_howToEnableUI != gPrintSetInterface.kFrameEnableNone) {
 
439
      if (dialog.aslaidoutRadio.selected) {
 
440
        frametype = gPrintSetInterface.kFramesAsIs;
 
441
      } else if (dialog.selectedframeRadio.selected) {
 
442
        frametype = gPrintSetInterface.kSelectedFrame;
 
443
      } else if (dialog.eachframesepRadio.selected) {
 
444
        frametype = gPrintSetInterface.kEachFrameSep;
 
445
      } else {
 
446
        frametype = gPrintSetInterface.kSelectedFrame;
 
447
      }
 
448
    }
 
449
    gPrintSettings.printFrameType = frametype;
 
450
    if (doDebug) {
 
451
      dump("onAccept*********************************************\n");
 
452
      dump("frametype      "+frametype+"\n");
 
453
      dump("numCopies      "+gPrintSettings.numCopies+"\n");
 
454
      dump("printRange     "+gPrintSettings.printRange+"\n");
 
455
      dump("printerName    "+gPrintSettings.printerName+"\n");
 
456
      dump("startPageRange "+gPrintSettings.startPageRange+"\n");
 
457
      dump("endPageRange   "+gPrintSettings.endPageRange+"\n");
 
458
      dump("printToFile    "+gPrintSettings.printToFile+"\n");
 
459
    }
 
460
  }
 
461
 
 
462
  if (printService) {
 
463
    var flags = gPrintSetInterface.kInitSavePaperSizeType | 
 
464
                gPrintSetInterface.kInitSavePaperSizeUnit |
 
465
                gPrintSetInterface.kInitSavePaperWidth    | 
 
466
                gPrintSetInterface.kInitSavePaperHeight   |
 
467
                gPrintSetInterface.kInitSavePaperName     | 
 
468
                gPrintSetInterface.kInitSaveInColor       |
 
469
                gPrintSetInterface.kInitSavePrintCommand;
 
470
    printService.savePrintSettingsToPrefs(gPrintSettings, true, flags);
 
471
  }
 
472
 
 
473
  // set return value to "print"
 
474
  if (paramBlock) {
 
475
    paramBlock.SetInt(0, 1);
 
476
  } else {
 
477
    dump("*** FATAL ERROR: No paramBlock\n");
 
478
  }
 
479
 
 
480
  return true;
 
481
 
 
482
}
 
483
 
 
484
//---------------------------------------------------
 
485
function onCancel()
 
486
{
 
487
  // set return value to "cancel"
 
488
  if (paramBlock) {
 
489
    paramBlock.SetInt(0, 0);
 
490
  } else {
 
491
    dump("*** FATAL ERROR: No paramBlock\n");
 
492
  }
 
493
 
 
494
  return true;
 
495
}
 
496
 
 
497
//---------------------------------------------------
 
498
const nsIFilePicker = Components.interfaces.nsIFilePicker;
 
499
function onChooseFile()
 
500
{
 
501
  if (dialog.fileRadio.selected == false)
 
502
    return;
 
503
 
 
504
  try {
 
505
    var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
 
506
    fp.init(window, dialog.fpDialog.getAttribute("label"), nsIFilePicker.modeSave);
 
507
    fp.appendFilters(nsIFilePicker.filterAll);
 
508
    fp.show();
 
509
    if (fp.file && fp.file.path.length > 0) {
 
510
      dialog.fileInput.value = fp.file.path;
 
511
      gFileFromPicker = dialog.fileInput.value;
 
512
    }
 
513
  } catch(ex) {
 
514
    dump(ex);
 
515
  }
 
516
}
 
517