1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) INRIA - Allan CORNET
4 *
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
6 *
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
13 *
14 */
15
16 /*--------------------------------------------------------------------------*/
17 #include "TextToPrint.h"
18 #include "sci_malloc.h"
19 #include "charEncoding.h"
20 #include "os_string.h"
21 /*--------------------------------------------------------------------------*/
22 static HDC PrinterHDC = NULL;
23 static char PrinterName[2048];
24 static char PrinterOrientation;
25 /*--------------------------------------------------------------------------*/
EzCreateFont(HDC hdc,TCHAR * szFaceName,int iDeciPtHeight,int iDeciPtWidth,int iAttributes,BOOL fLogRes)26 HFONT EzCreateFont (HDC hdc, TCHAR * szFaceName, int iDeciPtHeight, int iDeciPtWidth, int iAttributes, BOOL fLogRes)
27 {
28 FLOAT cxDpi, cyDpi ;
29 HFONT hFont ;
30 LOGFONT lf ;
31 POINT pt ;
32 TEXTMETRIC tm ;
33 SaveDC (hdc) ;
34 SetGraphicsMode (hdc, GM_ADVANCED) ;
35 ModifyWorldTransform (hdc, NULL, MWT_IDENTITY) ;
36 SetViewportOrgEx (hdc, 0, 0, NULL) ;
37 SetWindowOrgEx (hdc, 0, 0, NULL) ;
38 if (fLogRes)
39 {
40 cxDpi = (FLOAT) GetDeviceCaps (hdc, LOGPIXELSX) ;
41 cyDpi = (FLOAT) GetDeviceCaps (hdc, LOGPIXELSY) ;
42 }
43 else
44 {
45 cxDpi = (FLOAT) (25.4 * GetDeviceCaps (hdc, HORZRES) /
46 GetDeviceCaps (hdc, HORZSIZE)) ;
47 cyDpi = (FLOAT) (25.4 * GetDeviceCaps (hdc, VERTRES) /
48 GetDeviceCaps (hdc, VERTSIZE)) ;
49 }
50 pt.x = (int) (iDeciPtWidth * cxDpi / 72) ;
51 pt.y = (int) (iDeciPtHeight * cyDpi / 72) ;
52 DPtoLP (hdc, &pt, 1) ;
53
54 lf.lfHeight = - (int) (fabs (pt.y) / 10.0 + 0.5) ;
55 lf.lfWidth = 0 ;
56 lf.lfEscapement = 0 ;
57 lf.lfOrientation = 0 ;
58 lf.lfWeight = iAttributes & EZ_ATTR_BOLD ? 700 : 0 ;
59 lf.lfItalic = iAttributes & EZ_ATTR_ITALIC ? 1 : 0 ;
60 lf.lfUnderline = iAttributes & EZ_ATTR_UNDERLINE ? 1 : 0 ;
61 lf.lfStrikeOut = iAttributes & EZ_ATTR_STRIKEOUT ? 1 : 0 ;
62 lf.lfCharSet = DEFAULT_CHARSET ;
63 lf.lfOutPrecision = 0 ;
64 lf.lfClipPrecision = 0 ;
65 lf.lfQuality = 0 ;
66 lf.lfPitchAndFamily = 0 ;
67 lstrcpy (lf.lfFaceName, szFaceName) ;
68 hFont = CreateFontIndirect (&lf) ;
69 if (iDeciPtWidth != 0)
70 {
71 hFont = (HFONT) SelectObject (hdc, hFont) ;
72 GetTextMetrics (hdc, &tm) ;
73 DeleteObject (SelectObject (hdc, hFont)) ;
74 lf.lfWidth = (int) (tm.tmAveCharWidth *
75 fabs (pt.x) / fabs (pt.y) + 0.5) ;
76 hFont = CreateFontIndirect (&lf) ;
77 }
78 RestoreDC (hdc, -1) ;
79 return hFont ;
80 }
81 /*--------------------------------------------------------------------------*/
PrintString(char * lines,char * Entete)82 void PrintString(char *lines, char *Entete)
83 {
84 HDC PrintDC;
85 HFONT hFont, hOldFont;
86 HDC hDCmem;
87 DOCINFO di;
88 int TextLength = 0;
89 int i = 0;
90 int Index1 = 0;
91 int Index2 = 3;
92 int numero = 1;
93 // Extrait les informations sur la police
94 TEXTMETRIC tm;
95 int NbLigneParPage = 0;
96 int HauteurCaractere = 0;
97 int NombredeCaracteresparLignes = 0;
98
99
100 PrintDC = GetPrinterDC();
101 if (PrintDC != NULL)
102 {
103 hFont = EzCreateFont (PrintDC, TEXT ("Courier New"), 120, 0, 0, TRUE) ;
104
105 hOldFont = SelectObject(PrintDC, hFont );
106
107 hDCmem = CreateCompatibleDC(PrintDC);
108 memset( &di, 0, sizeof( DOCINFO ) );
109 di.cbSize = sizeof( DOCINFO );
110 di.lpszDocName = "Scilab Document";
111
112 TextLength = (int)strlen(lines);
113
114 GetTextMetrics(PrintDC, (TEXTMETRIC *)&tm);
115
116 NombredeCaracteresparLignes = GetDeviceCaps(PrintDC, HORZRES) / (tm.tmMaxCharWidth + 1);
117 // la valeur HauteurCaractere contient hauteur des caract�res + l'interligne
118 HauteurCaractere = tm.tmHeight + tm.tmExternalLeading;
119 NbLigneParPage = GetDeviceCaps(PrintDC, VERTRES) / HauteurCaractere;
120
121 if (TextLength > 0)
122 {
123 if ( StartDoc( PrintDC, &di ) > 0 )
124 {
125 char *LignePrint = NULL;
126 LignePrint = (char*)MALLOC((NombredeCaracteresparLignes + 1) * sizeof(char));
127
128 StartPage(PrintDC);
129 PageHeader(PrintDC, Entete);
130 for (i = 0; i < TextLength; i++)
131 {
132 LignePrint[Index1] = lines[i];
133 if ( Index1 == NombredeCaracteresparLignes )
134 {
135 Index2 ++;
136 LignePrint[Index1] = '\0';
137 if (LignePrint[Index1 - 1] == '\r')
138 {
139 LignePrint[Index1 - 1] = '\0';
140 }
141 TextOut (PrintDC, (tm.tmMaxCharWidth + 10), Index2 * HauteurCaractere, LignePrint, (int)strlen(LignePrint));
142 Index1 = 0;
143 if (LignePrint)
144 {
145 FREE(LignePrint);
146 LignePrint = NULL;
147 }
148 LignePrint = (char*)MALLOC((NombredeCaracteresparLignes + 1) * sizeof(char));
149 }
150 else if ( (lines[i] == '\n') )
151 {
152 Index2 ++;
153 if (Index1 > 0)
154 {
155 LignePrint[Index1] = '\0';
156 if (LignePrint[Index1 - 1] == '\r')
157 {
158 LignePrint[Index1 - 1] = '\0';
159 }
160 TextOut (PrintDC, (tm.tmMaxCharWidth + 10), Index2 * HauteurCaractere, LignePrint, (int)strlen(LignePrint));
161 Index1 = 0;
162 }
163 if (LignePrint)
164 {
165 FREE(LignePrint);
166 LignePrint = NULL;
167 }
168 LignePrint = (char*)MALLOC((NombredeCaracteresparLignes + 1) * sizeof(char));
169 }
170 else
171 {
172 Index1 ++;
173 }
174 if (Index2 == NbLigneParPage - 4)
175 {
176 Footer(PrintDC, numero);
177 EndPage (PrintDC);
178 StartPage(PrintDC);
179 numero++;
180 PageHeader(PrintDC, Entete);
181 Index2 = 3;
182 }
183 }
184 Index2 ++;
185 LignePrint[Index1] = '\0';
186 TextOut (PrintDC, (tm.tmMaxCharWidth + 10), Index2 * HauteurCaractere, LignePrint, (int) strlen(LignePrint));
187 Footer(PrintDC, numero);
188 EndPage (PrintDC);
189 EndDoc (PrintDC);
190
191 if (LignePrint)
192 {
193 FREE(LignePrint);
194 LignePrint = NULL;
195 }
196 }
197 }
198 SelectObject(PrintDC, hOldFont );
199 }
200
201 }
202 /*--------------------------------------------------------------------------*/
PrintFile(char * filename)203 void PrintFile(char *filename)
204 {
205 #define MAXBUF 4096
206 HDC PrintDC;
207 HFONT hFont, hOldFont;
208 HDC hDCmem;
209 DOCINFO di;
210 int Index2 = 3;
211 int numero = 1;
212 // Extrait les informations sur la police
213 TEXTMETRIC tm;
214 int NbLigneParPage = 0;
215 int HauteurCaractere = 0;
216 int NombredeCaracteresparLignes = 0;
217 FILE * pFile;
218 char line[MAXBUF];
219
220 PrintDC = GetPrinterDC();
221 if (PrintDC != NULL)
222 {
223
224 hFont = EzCreateFont (PrintDC, TEXT ("Courier New"), 120, 0, 0, TRUE) ;
225 hOldFont = SelectObject(PrintDC, hFont );
226
227 hDCmem = CreateCompatibleDC(PrintDC);
228 memset( &di, 0, sizeof( DOCINFO ) );
229 di.cbSize = sizeof( DOCINFO );
230 di.lpszDocName = "Scilab Document";
231
232 GetTextMetrics(PrintDC, (TEXTMETRIC *)&tm);
233
234 NombredeCaracteresparLignes = GetDeviceCaps(PrintDC, HORZRES) / (tm.tmMaxCharWidth + 1);
235 // la valeur HauteurCaractere contient hauteur des caract�res + l'interligne
236 HauteurCaractere = tm.tmHeight + tm.tmExternalLeading;
237 NbLigneParPage = GetDeviceCaps(PrintDC, VERTRES) / HauteurCaractere;
238
239 wcfopen(pFile , filename, "rt");
240
241 if (pFile)
242 {
243 if ( StartDoc( PrintDC, &di ) > 0 )
244 {
245 char *LignePrint = NULL;
246 StartPage(PrintDC);
247 PageHeader(PrintDC, filename);
248
249 while (fgets (line, sizeof(line), pFile) != NULL)
250 {
251 if (line[strlen(line) - 1] == '\n')
252 {
253 line[strlen(line) - 1] = '\0'; /* enleve le retour chariot */
254 }
255 if (line[strlen(line) - 2] == '\r')
256 {
257 line[strlen(line) - 2] = '\0'; /* enleve le retour chariot */
258 }
259
260 if ( strlen(line) > (unsigned int )NombredeCaracteresparLignes)
261 {
262 int i = 0;
263 int j = 0;
264 int subline = 0;
265 int restsubline = 0;
266 subline = (int)strlen(line) / NombredeCaracteresparLignes ;
267 restsubline = (int)strlen(line) % NombredeCaracteresparLignes ;
268
269 for (i = 0; i < subline; i++)
270 {
271 LignePrint = (char*)MALLOC( (NombredeCaracteresparLignes + 1) * sizeof(char));
272 for (j = 0; j < (NombredeCaracteresparLignes); j++)
273 {
274 if (line[(i * NombredeCaracteresparLignes) + j] == 9) /* == \t */
275 {
276 LignePrint[j] = ' ';
277 }
278 else
279 {
280 LignePrint[j] = line[(i * NombredeCaracteresparLignes) + j];
281 }
282
283 }
284 LignePrint[j] = '\0';
285
286 TextOut (PrintDC, (tm.tmMaxCharWidth + 10), Index2 * HauteurCaractere, LignePrint, (int)strlen(LignePrint));
287 if (LignePrint)
288 {
289 FREE(LignePrint);
290 LignePrint = NULL;
291 }
292 Index2 ++;
293 if (Index2 == NbLigneParPage - 4)
294 {
295 Footer(PrintDC, numero);
296 EndPage (PrintDC);
297 StartPage(PrintDC);
298 numero++;
299 PageHeader(PrintDC, filename);
300 Index2 = 3;
301 }
302 }
303 if (restsubline > 0)
304 {
305 LignePrint = (char*)MALLOC( (NombredeCaracteresparLignes + 1) * sizeof(char));
306 for (j = 0; j < (restsubline); j++)
307 {
308 if (line[(i * NombredeCaracteresparLignes) + j] == 9) /* == \t */
309 {
310 LignePrint[j] = ' ';
311 }
312 else
313 {
314 LignePrint[j] = line[(i * NombredeCaracteresparLignes) + j];
315 }
316 }
317 LignePrint[j] = '\0';
318 TextOut (PrintDC, (tm.tmMaxCharWidth + 10), Index2 * HauteurCaractere, LignePrint, (int)strlen(LignePrint));
319 if (LignePrint)
320 {
321 FREE(LignePrint);
322 LignePrint = NULL;
323 }
324 Index2 ++;
325 if (Index2 == NbLigneParPage - 4)
326 {
327 Footer(PrintDC, numero);
328 EndPage (PrintDC);
329 StartPage(PrintDC);
330 numero++;
331 PageHeader(PrintDC, filename);
332 Index2 = 3;
333 }
334 }
335 }
336 else
337 {
338 LignePrint = os_strdup(line);
339 TextOut (PrintDC, (tm.tmMaxCharWidth + 10), Index2 * HauteurCaractere, LignePrint, (int)strlen(LignePrint));
340 if (LignePrint)
341 {
342 FREE(LignePrint);
343 LignePrint = NULL;
344 }
345 Index2 ++;
346 if (Index2 == NbLigneParPage - 4)
347 {
348 Footer(PrintDC, numero);
349 EndPage (PrintDC);
350 StartPage(PrintDC);
351 numero++;
352 PageHeader(PrintDC, filename);
353 Index2 = 3;
354 }
355 }
356 }
357 fclose(pFile);
358
359 Footer(PrintDC, numero);
360 EndPage (PrintDC);
361 EndDoc (PrintDC);
362 }
363 }
364 SelectObject(PrintDC, hOldFont );
365 }
366 }
367 /*--------------------------------------------------------------------------*/
Footer(HDC hdc,int number)368 void Footer(HDC hdc, int number)
369 {
370 HPEN hPen, hPenOld;
371 LOGBRUSH lb;
372 int NombredeCaracteresparLignes = 0;
373 TEXTMETRIC tm;
374 int yChar = 0;
375 char *ptrLine = NULL;
376
377 int CySize = GetDeviceCaps(hdc, VERTRES);
378 // Initialize the pen's brush.
379 lb.lbStyle = BS_SOLID;
380 lb.lbColor = RGB(0, 0, 0);
381 lb.lbHatch = 0;
382
383 GetTextMetrics (hdc, (TEXTMETRIC *) & tm);
384 NombredeCaracteresparLignes = tm.tmMaxCharWidth + 10;
385 yChar = tm.tmHeight + tm.tmExternalLeading ;
386 ptrLine = (char*)MALLOC( (NombredeCaracteresparLignes + 1) * sizeof(char));
387
388 hPen = ExtCreatePen(PS_SOLID, 1, &lb, 0, NULL);
389 hPenOld = SelectObject(hdc, hPen);
390
391 MoveToEx(hdc, (tm.tmMaxCharWidth + 10), CySize - (yChar * 3) - 10, NULL);
392 LineTo(hdc, GetDeviceCaps(hdc, HORZRES) - (tm.tmMaxCharWidth + 10), CySize - (yChar * 3) - 10);
393
394 SelectObject(hdc, hPenOld);
395 DeleteObject(hPen);
396
397 wsprintf(ptrLine, "Page : %d", number);
398 TextOut(hdc, (tm.tmMaxCharWidth + 10), CySize - (yChar * 3), ptrLine, (int)strlen(ptrLine));
399 FREE(ptrLine);
400 }
401 /*--------------------------------------------------------------------------*/
PageHeader(HDC hdc,LPSTR Entete)402 void PageHeader(HDC hdc, LPSTR Entete)
403 {
404 HPEN hPen, hPenOld;
405 LOGBRUSH lb;
406
407 TEXTMETRIC tm;
408 int NbLigneParPage = 0;
409 int HauteurCaractere = 0;
410 int NombredeCaracteresparLignes = 0;
411 int NombredeLignesOccupeesparEntete = 1;
412
413 char dbuffer [9];
414 char tbuffer [9];
415 char *ptrLine = NULL;
416
417 // Initialize the pen's brush.
418 lb.lbStyle = BS_SOLID;
419 lb.lbColor = RGB(0, 0, 0);
420 lb.lbHatch = 0;
421
422 _strdate( dbuffer );
423 _strtime( tbuffer );
424
425 GetTextMetrics (hdc, (TEXTMETRIC *) & tm);
426
427 NombredeCaracteresparLignes = GetDeviceCaps(hdc, HORZRES) / (tm.tmMaxCharWidth + 10);
428 // la valeur HauteurCaractere contient hauteur des caract�res + l'interligne
429 HauteurCaractere = tm.tmHeight + tm.tmExternalLeading;
430 NbLigneParPage = GetDeviceCaps(hdc, VERTRES) / HauteurCaractere;
431
432 ptrLine = (char*)MALLOC( (NombredeCaracteresparLignes + 1) * sizeof(char));
433 wsprintf(ptrLine, "%s %s %s", dbuffer, tbuffer, Entete);
434
435 TextOut(hdc, (tm.tmMaxCharWidth + 10), NombredeLignesOccupeesparEntete * HauteurCaractere, ptrLine, (int)strlen(ptrLine));
436 NombredeLignesOccupeesparEntete++;
437
438 hPen = ExtCreatePen(PS_SOLID, 1, &lb, 0, NULL);
439 hPenOld = SelectObject(hdc, hPen);
440
441 MoveToEx(hdc, (tm.tmMaxCharWidth + 10), NombredeLignesOccupeesparEntete * HauteurCaractere, NULL);
442 LineTo(hdc, GetDeviceCaps(hdc, HORZRES) - (tm.tmMaxCharWidth + 10), NombredeLignesOccupeesparEntete * HauteurCaractere);
443
444 SelectObject(hdc, hPenOld);
445 DeleteObject(hPen);
446
447 FREE(ptrLine);
448
449 }
450 /*--------------------------------------------------------------------------*/
CutLineForDisplay(char * CutLine,char * Line,int NumberOfCharByLine)451 void CutLineForDisplay(char *CutLine, char *Line, int NumberOfCharByLine)
452 {
453 int LenLine = lstrlen(Line);
454
455 if (LenLine > NumberOfCharByLine)
456 {
457 int NumberOfLines = lstrlen(Line) / NumberOfCharByLine;
458 int i = 0;
459 char *Buffer = NULL;
460
461 Buffer = (char*)MALLOC((LenLine + NumberOfLines + 1) * sizeof(char));
462 for (i = 0; i < NumberOfLines + 1; i++)
463 {
464 if ( i == 0)
465 {
466 lstrcpyn(Buffer, &Line[i * NumberOfCharByLine], NumberOfCharByLine);
467
468 }
469 else
470 {
471 char BufferCat[MAX_PATH];
472 lstrcpyn(BufferCat, &Line[i * NumberOfCharByLine], NumberOfCharByLine);
473 lstrcat(Buffer, BufferCat);
474
475 }
476 if (i != NumberOfLines)
477 {
478 lstrcat(Buffer, "\n");
479 }
480 }
481 lstrcpy(CutLine, Buffer);
482
483 FREE(Buffer);
484 }
485 else
486 {
487 wsprintf(CutLine, "%s", Line);
488 }
489 }
490 /*--------------------------------------------------------------------------*/
ConfigurePrinterDialogBox(void)491 BOOL ConfigurePrinterDialogBox(void)
492 {
493 BOOL bOK = FALSE;
494
495 PRINTDLG pd;
496
497 if (PrinterHDC)
498 {
499 DeleteDC(PrinterHDC);
500 PrinterHDC = NULL;
501 }
502 wsprintf(PrinterName, "%s", "EMPTY");
503 PrinterOrientation = 'p';
504
505 memset (&pd, 0, sizeof (PRINTDLG));
506 pd.lStructSize = sizeof (PRINTDLG);
507 pd.hwndOwner = NULL;
508 pd.hDevMode = NULL;
509 pd.hDevNames = NULL;
510 pd.hDC = NULL;
511 pd.Flags = PD_ALLPAGES | PD_COLLATE | PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | PD_NOSELECTION | PD_HIDEPRINTTOFILE | PD_NONETWORKBUTTON;
512 pd.nFromPage = 0;
513 pd.nToPage = 0;
514 pd.nMinPage = 0;
515 pd.nMaxPage = 0;
516 pd.nCopies = 1;
517 pd.hInstance = NULL;
518 pd.lCustData = 0L;
519 pd.lpfnPrintHook = NULL;
520 pd.lpfnSetupHook = NULL;
521 pd.lpPrintTemplateName = NULL;
522 pd.lpSetupTemplateName = NULL;
523 pd.hPrintTemplate = NULL;
524 pd.hSetupTemplate = NULL;
525 if (PrintDlg (&pd) == FALSE)
526 {
527 wsprintf(PrinterName, "%s", "EMPTY");
528 PrinterOrientation = 'p';
529 PrinterHDC = NULL;
530 bOK = FALSE;
531 }
532 else
533 {
534 LPDEVNAMES lpDev = (LPDEVNAMES)GlobalLock(pd.hDevNames);
535 LPDEVMODE lpDevMode = (LPDEVMODE)GlobalLock(pd.hDevMode);
536 LPCTSTR lpszDevice = (LPCTSTR)lpDev + lpDev->wDeviceOffset;
537
538 wsprintf(PrinterName, "%s", lpszDevice);
539 GlobalUnlock(pd.hDevNames);
540
541 if (lpDevMode->dmOrientation == DMORIENT_PORTRAIT )
542 {
543 PrinterOrientation = 'p';
544 }
545 else
546 {
547 PrinterOrientation = 'l';
548 }
549 GlobalUnlock(pd.hDevMode);
550
551 if (PrinterHDC)
552 {
553 DeleteDC(PrinterHDC);
554 PrinterHDC = NULL;
555 }
556 PrinterHDC = pd.hDC;
557 bOK = TRUE;
558 }
559
560 return bOK;
561 }
562 /*--------------------------------------------------------------------------*/
GetPrinterDC(void)563 HDC GetPrinterDC(void)
564 {
565 if (PrinterHDC == NULL)
566 {
567 PRINTDLG pd;
568 LPDEVNAMES lpDev = NULL;
569 LPDEVMODE lpDevMode = NULL;
570 LPCTSTR lpszDevice = NULL;
571
572 int failed = 0;
573
574 // Reset printdlg struct
575 memset( &pd, 0, sizeof(PRINTDLG) );
576 pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
577 pd.lStructSize = sizeof( PRINTDLG );
578
579
580 failed = ( ! PrintDlg( &pd ) );
581 if (failed)
582 {
583 ConfigurePrinterDialogBox();
584 }
585
586 lpDev = (LPDEVNAMES)GlobalLock(pd.hDevNames);
587 lpDevMode = (LPDEVMODE)GlobalLock(pd.hDevMode);
588 lpszDevice = (LPCTSTR)lpDev + lpDev->wDeviceOffset;
589
590 wsprintf(PrinterName, "%s", lpszDevice);
591 GlobalUnlock(pd.hDevNames);
592
593 if (lpDevMode->dmOrientation == DMORIENT_PORTRAIT )
594 {
595 PrinterOrientation = 'p';
596 }
597 else
598 {
599 PrinterOrientation = 'l';
600 }
601 GlobalUnlock(pd.hDevMode);
602
603 if (PrinterHDC)
604 {
605 DeleteDC(PrinterHDC);
606 PrinterHDC = NULL;
607 }
608 PrinterHDC = pd.hDC;
609
610 }
611
612 return PrinterHDC;
613 }
614 /*--------------------------------------------------------------------------*/
GetPrinterOrientation(void)615 char GetPrinterOrientation(void)
616 {
617 return PrinterOrientation;
618 }
619 /*--------------------------------------------------------------------------*/
GetPrinterName(void)620 char* GetPrinterName(void)
621 {
622 char *ReturnPrinterName = NULL;
623
624 ReturnPrinterName = MALLOC(strlen(PrinterName) * sizeof(char));
625 wsprintf(ReturnPrinterName, "%s", PrinterName);
626
627 return ReturnPrinterName;
628 }
629 /*--------------------------------------------------------------------------*/
630