|
Packit |
b099d7 |
/* $TOG: XpmWrFFrI.c /main/3 1998/07/22 15:43:49 mgreess $ */
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* Copyright (C) 1989-95 GROUPE BULL
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
b099d7 |
* of this software and associated documentation files (the "Software"), to
|
|
Packit |
b099d7 |
* deal in the Software without restriction, including without limitation the
|
|
Packit |
b099d7 |
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
Packit |
b099d7 |
* sell copies of the Software, and to permit persons to whom the Software is
|
|
Packit |
b099d7 |
* furnished to do so, subject to the following conditions:
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* The above copyright notice and this permission notice shall be included in
|
|
Packit |
b099d7 |
* all copies or substantial portions of the Software.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
Packit |
b099d7 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
Packit |
b099d7 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
Packit |
b099d7 |
* GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
Packit |
b099d7 |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
b099d7 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit |
b099d7 |
*
|
|
Packit |
b099d7 |
* Except as contained in this notice, the name of GROUPE BULL shall not be
|
|
Packit |
b099d7 |
* used in advertising or otherwise to promote the sale, use or other dealings
|
|
Packit |
b099d7 |
* in this Software without prior written authorization from GROUPE BULL.
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*****************************************************************************\
|
|
Packit |
b099d7 |
* WrFFrI.c: *
|
|
Packit |
b099d7 |
* *
|
|
Packit |
b099d7 |
* XPM library *
|
|
Packit |
b099d7 |
* Write an image and possibly its mask to an XPM file *
|
|
Packit |
b099d7 |
* *
|
|
Packit |
b099d7 |
* Developed by Arnaud Le Hors *
|
|
Packit |
b099d7 |
\*****************************************************************************/
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
b099d7 |
#include <config.h>
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
#include "XpmI.h"
|
|
Packit |
b099d7 |
#if !defined(NO_ZPIPE) && defined(WIN32)
|
|
Packit |
b099d7 |
# define popen _popen
|
|
Packit |
b099d7 |
# define pclose _pclose
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* MS Windows define a function called WriteFile @#%#&!!! */
|
|
Packit |
b099d7 |
LFUNC(xpmWriteFile, int, (FILE *file, XpmImage *image, char *name,
|
|
Packit |
b099d7 |
XpmInfo *info));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
LFUNC(WriteColors, void, (FILE *file, XpmColor *colors, unsigned int ncolors));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
LFUNC(WritePixels, int, (FILE *file, unsigned int width, unsigned int height,
|
|
Packit |
b099d7 |
unsigned int cpp, unsigned int *pixels,
|
|
Packit |
b099d7 |
XpmColor *colors));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
LFUNC(WriteExtensions, void, (FILE *file, XpmExtension *ext,
|
|
Packit |
b099d7 |
unsigned int num));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
LFUNC(OpenWriteFile, int, (char *filename, xpmData *mdata));
|
|
Packit |
b099d7 |
LFUNC(xpmDataClose, void, (xpmData *mdata));
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
int
|
|
Packit |
b099d7 |
XpmWriteFileFromImage(display, filename, image, shapeimage, attributes)
|
|
Packit |
b099d7 |
Display *display;
|
|
Packit |
b099d7 |
char *filename;
|
|
Packit |
b099d7 |
XImage *image;
|
|
Packit |
b099d7 |
XImage *shapeimage;
|
|
Packit |
b099d7 |
XpmAttributes *attributes;
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
XpmImage xpmimage;
|
|
Packit |
b099d7 |
XpmInfo info;
|
|
Packit |
b099d7 |
int ErrorStatus;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* create an XpmImage from the image */
|
|
Packit |
b099d7 |
ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
|
|
Packit |
b099d7 |
&xpmimage, attributes);
|
|
Packit |
b099d7 |
if (ErrorStatus != XpmSuccess)
|
|
Packit |
b099d7 |
return (ErrorStatus);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* write the file from the XpmImage */
|
|
Packit |
b099d7 |
if (attributes) {
|
|
Packit |
b099d7 |
xpmSetInfo(&info, attributes);
|
|
Packit |
b099d7 |
ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, &info;;
|
|
Packit |
b099d7 |
} else
|
|
Packit |
b099d7 |
ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, NULL);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* free the XpmImage */
|
|
Packit |
b099d7 |
XpmFreeXpmImage(&xpmimage);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return (ErrorStatus);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
int
|
|
Packit |
b099d7 |
XpmWriteFileFromXpmImage(filename, image, info)
|
|
Packit |
b099d7 |
char *filename;
|
|
Packit |
b099d7 |
XpmImage *image;
|
|
Packit |
b099d7 |
XpmInfo *info;
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
xpmData mdata;
|
|
Packit |
b099d7 |
char *name, *dot, *s, new_name[BUFSIZ] = {0};
|
|
Packit |
b099d7 |
int ErrorStatus;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* open file to write */
|
|
Packit |
b099d7 |
if ((ErrorStatus = OpenWriteFile(filename, &mdata)) != XpmSuccess)
|
|
Packit |
b099d7 |
return (ErrorStatus);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* figure out a name */
|
|
Packit |
b099d7 |
if (filename) {
|
|
Packit |
b099d7 |
#ifdef VMS
|
|
Packit |
b099d7 |
name = filename;
|
|
Packit |
b099d7 |
#else
|
|
Packit |
b099d7 |
if (!(name = rindex(filename, '/')))
|
|
Packit |
b099d7 |
name = filename;
|
|
Packit |
b099d7 |
else
|
|
Packit |
b099d7 |
name++;
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
/* let's try to make a valid C syntax name */
|
|
Packit |
b099d7 |
if ((dot = index(name, '.'))) {
|
|
Packit |
b099d7 |
strncpy(new_name, name, sizeof(new_name));
|
|
Packit |
b099d7 |
new_name[sizeof(new_name)-1] = 0;
|
|
Packit |
b099d7 |
/* change '.' to '_' */
|
|
Packit |
b099d7 |
name = s = new_name;
|
|
Packit |
b099d7 |
while ((dot = index(s, '.'))) {
|
|
Packit |
b099d7 |
*dot = '_';
|
|
Packit |
b099d7 |
s = dot;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
if ((dot = index(name, '-'))) {
|
|
Packit |
b099d7 |
if (name != new_name) {
|
|
Packit |
b099d7 |
strncpy(new_name, name, sizeof(new_name));
|
|
Packit |
b099d7 |
new_name[sizeof(new_name)-1] = 0;
|
|
Packit |
b099d7 |
name = new_name;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
/* change '-' to '_' */
|
|
Packit |
b099d7 |
s = name;
|
|
Packit |
b099d7 |
while ((dot = index(s, '-'))) {
|
|
Packit |
b099d7 |
*dot = '_';
|
|
Packit |
b099d7 |
s = dot;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
} else
|
|
Packit |
b099d7 |
name = "image_name";
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* write the XpmData from the XpmImage */
|
|
Packit |
b099d7 |
if (ErrorStatus == XpmSuccess)
|
|
Packit |
b099d7 |
ErrorStatus = xpmWriteFile(mdata.stream.file, image, name, info);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
xpmDataClose(&mdata);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return (ErrorStatus);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static int
|
|
Packit |
b099d7 |
xpmWriteFile(file, image, name, info)
|
|
Packit |
b099d7 |
FILE *file;
|
|
Packit |
b099d7 |
XpmImage *image;
|
|
Packit |
b099d7 |
char *name;
|
|
Packit |
b099d7 |
XpmInfo *info;
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
/* calculation variables */
|
|
Packit |
b099d7 |
unsigned int cmts, extensions;
|
|
Packit |
b099d7 |
int ErrorStatus;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
cmts = info && (info->valuemask & XpmComments);
|
|
Packit |
b099d7 |
extensions = info && (info->valuemask & XpmExtensions)
|
|
Packit |
b099d7 |
&& info->nextensions;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* print the header line */
|
|
Packit |
b099d7 |
fprintf(file, "/* XPM */\nstatic char * %s[] = {\n", name);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* print the hints line */
|
|
Packit |
b099d7 |
if (cmts && info->hints_cmt)
|
|
Packit |
b099d7 |
fprintf(file, "/*%s*/\n", info->hints_cmt);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
fprintf(file, "\"%d %d %d %d", image->width, image->height,
|
|
Packit |
b099d7 |
image->ncolors, image->cpp);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (info && (info->valuemask & XpmHotspot))
|
|
Packit |
b099d7 |
fprintf(file, " %d %d", info->x_hotspot, info->y_hotspot);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (extensions)
|
|
Packit |
b099d7 |
fprintf(file, " XPMEXT");
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
fprintf(file, "\",\n");
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* print colors */
|
|
Packit |
b099d7 |
if (cmts && info->colors_cmt)
|
|
Packit |
b099d7 |
fprintf(file, "/*%s*/\n", info->colors_cmt);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
WriteColors(file, image->colorTable, image->ncolors);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* print pixels */
|
|
Packit |
b099d7 |
if (cmts && info->pixels_cmt)
|
|
Packit |
b099d7 |
fprintf(file, "/*%s*/\n", info->pixels_cmt);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
ErrorStatus = WritePixels(file, image->width, image->height, image->cpp,
|
|
Packit |
b099d7 |
image->data, image->colorTable);
|
|
Packit |
b099d7 |
if (ErrorStatus != XpmSuccess)
|
|
Packit |
b099d7 |
return (ErrorStatus);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* print extensions */
|
|
Packit |
b099d7 |
if (extensions)
|
|
Packit |
b099d7 |
WriteExtensions(file, info->extensions, info->nextensions);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/* close the array */
|
|
Packit |
b099d7 |
fprintf(file, "};\n");
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
return (XpmSuccess);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static void
|
|
Packit |
b099d7 |
WriteColors(file, colors, ncolors)
|
|
Packit |
b099d7 |
FILE *file;
|
|
Packit |
b099d7 |
XpmColor *colors;
|
|
Packit |
b099d7 |
unsigned int ncolors;
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
unsigned int a, key;
|
|
Packit |
b099d7 |
char *s;
|
|
Packit |
b099d7 |
char **defaults;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
for (a = 0; a < ncolors; a++, colors++) {
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
defaults = (char **) colors;
|
|
Packit |
b099d7 |
fprintf(file, "\"%s", *defaults++);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
for (key = 1; key <= NKEYS; key++, defaults++) {
|
|
Packit |
b099d7 |
if ((s = *defaults))
|
|
Packit |
b099d7 |
fprintf(file, "\t%s %s", xpmColorKeys[key - 1], s);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
fprintf(file, "\",\n");
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static int
|
|
Packit |
b099d7 |
WritePixels(file, width, height, cpp, pixels, colors)
|
|
Packit |
b099d7 |
FILE *file;
|
|
Packit |
b099d7 |
unsigned int width;
|
|
Packit |
b099d7 |
unsigned int height;
|
|
Packit |
b099d7 |
unsigned int cpp;
|
|
Packit |
b099d7 |
unsigned int *pixels;
|
|
Packit |
b099d7 |
XpmColor *colors;
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
char *s, *p, *buf;
|
|
Packit |
b099d7 |
unsigned int x, y, h;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
h = height - 1;
|
|
Packit |
b099d7 |
if (cpp != 0 && width >= (UINT_MAX - 3)/cpp)
|
|
Packit |
b099d7 |
return XpmNoMemory;
|
|
Packit |
b099d7 |
p = buf = (char *) XpmMalloc(width * cpp + 3);
|
|
Packit |
b099d7 |
if (!buf)
|
|
Packit |
b099d7 |
return (XpmNoMemory);
|
|
Packit |
b099d7 |
*buf = '"';
|
|
Packit |
b099d7 |
p++;
|
|
Packit |
b099d7 |
for (y = 0; y < h; y++) {
|
|
Packit |
b099d7 |
s = p;
|
|
Packit |
b099d7 |
for (x = 0; x < width; x++, pixels++) {
|
|
Packit |
b099d7 |
strncpy(s, colors[*pixels].string, cpp);
|
|
Packit |
b099d7 |
s += cpp;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
*s++ = '"';
|
|
Packit |
b099d7 |
*s = '\0';
|
|
Packit |
b099d7 |
fprintf(file, "%s,\n", buf);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
/* duplicate some code to avoid a test in the loop */
|
|
Packit |
b099d7 |
s = p;
|
|
Packit |
b099d7 |
for (x = 0; x < width; x++, pixels++) {
|
|
Packit |
b099d7 |
strncpy(s, colors[*pixels].string, cpp);
|
|
Packit |
b099d7 |
s += cpp;
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
*s++ = '"';
|
|
Packit |
b099d7 |
*s = '\0';
|
|
Packit |
b099d7 |
fprintf(file, "%s", buf);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
XpmFree(buf);
|
|
Packit |
b099d7 |
return (XpmSuccess);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
static void
|
|
Packit |
b099d7 |
WriteExtensions(file, ext, num)
|
|
Packit |
b099d7 |
FILE *file;
|
|
Packit |
b099d7 |
XpmExtension *ext;
|
|
Packit |
b099d7 |
unsigned int num;
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
unsigned int x, y, n;
|
|
Packit |
b099d7 |
char **line;
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
for (x = 0; x < num; x++, ext++) {
|
|
Packit |
b099d7 |
fprintf(file, ",\n\"XPMEXT %s\"", ext->name);
|
|
Packit |
b099d7 |
n = ext->nlines;
|
|
Packit |
b099d7 |
for (y = 0, line = ext->lines; y < n; y++, line++)
|
|
Packit |
b099d7 |
fprintf(file, ",\n\"%s\"", *line);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
fprintf(file, ",\n\"XPMENDEXT\"");
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* open the given file to be written as an xpmData which is returned
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
#ifndef NO_ZPIPE
|
|
Packit |
b099d7 |
FILE *Xpms_popen(char *cmd, const char *type);
|
|
Packit |
b099d7 |
#else
|
|
Packit |
b099d7 |
# define Xpms_popen popen
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
static int
|
|
Packit |
b099d7 |
OpenWriteFile(filename, mdata)
|
|
Packit |
b099d7 |
char *filename;
|
|
Packit |
b099d7 |
xpmData *mdata;
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
#ifndef NO_ZPIPE
|
|
Packit |
b099d7 |
char buf[BUFSIZ];
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (!filename) {
|
|
Packit |
b099d7 |
mdata->stream.file = (stdout);
|
|
Packit |
b099d7 |
mdata->type = XPMFILE;
|
|
Packit |
b099d7 |
} else {
|
|
Packit |
b099d7 |
#ifndef NO_ZPIPE
|
|
Packit |
b099d7 |
size_t len = strlen(filename);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if(len == 0)
|
|
Packit |
b099d7 |
return(XpmOpenFailed);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
if (len > 2 && !strcmp(".Z", filename + (len - 2))) {
|
|
Packit |
b099d7 |
snprintf(buf, sizeof(buf), "compress > \"%s\"", filename);
|
|
Packit |
b099d7 |
if (!(mdata->stream.file = Xpms_popen(buf, "w")))
|
|
Packit |
b099d7 |
return (XpmOpenFailed);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
mdata->type = XPMPIPE;
|
|
Packit |
b099d7 |
} else if (len > 3 && !strcmp(".gz", filename + (len - 3))) {
|
|
Packit |
b099d7 |
snprintf(buf, sizeof(buf), "gzip -q > \"%s\"", filename);
|
|
Packit |
b099d7 |
if (!(mdata->stream.file = Xpms_popen(buf, "w")))
|
|
Packit |
b099d7 |
return (XpmOpenFailed);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
mdata->type = XPMPIPE;
|
|
Packit |
b099d7 |
} else {
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
if (!(mdata->stream.file = fopen(filename, "w")))
|
|
Packit |
b099d7 |
return (XpmOpenFailed);
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
mdata->type = XPMFILE;
|
|
Packit |
b099d7 |
#ifndef NO_ZPIPE
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
return (XpmSuccess);
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
|
|
Packit |
b099d7 |
/*
|
|
Packit |
b099d7 |
* close the file related to the xpmData if any
|
|
Packit |
b099d7 |
*/
|
|
Packit |
b099d7 |
static void
|
|
Packit |
b099d7 |
xpmDataClose(mdata)
|
|
Packit |
b099d7 |
xpmData *mdata;
|
|
Packit |
b099d7 |
{
|
|
Packit |
b099d7 |
switch (mdata->type) {
|
|
Packit |
b099d7 |
case XPMFILE:
|
|
Packit |
b099d7 |
if (mdata->stream.file != (stdout))
|
|
Packit |
b099d7 |
fclose(mdata->stream.file);
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
#ifndef NO_ZPIPE
|
|
Packit |
b099d7 |
case XPMPIPE:
|
|
Packit |
b099d7 |
fclose(mdata->stream.file);
|
|
Packit |
b099d7 |
break;
|
|
Packit |
b099d7 |
#endif
|
|
Packit |
b099d7 |
}
|
|
Packit |
b099d7 |
}
|