/* * pixmap_image.cc * * Copyright (C) 1995, 1996, 1997, 1997, 1998, 1999, 2000, 2001, 2002 Kenichi Kourai * Copyright (C) 1999, 2000, 2001, 2002 Luiz Blanes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with blwm; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "main.h" #include "pixmap_image.h" // // Xpm file format able to be read // " " // " c " // ... // "data for line0" // ... // // - ignore lines not beginning with " // - " must be the first character of a line // PixmapImage::PixmapImage(char* filename) { FILE* fp; struct stat st; char* raw; if ((fp = fopen(filename, "r")) == NULL) { BlwmError("cannot open file: '%s'", filename); m_error = IMG_OPEN_ERROR; return; } if (fstat(fileno(fp), &st) < 0) { BlwmError("cannot access file: '%s'", filename); m_error = IMG_FILE_ERROR; fclose(fp); return; } raw = new char[st.st_size]; if (fread(raw, st.st_size, 1, fp) < 1) { BlwmError("cannot read file: '%s'", filename); m_error = IMG_FILE_ERROR; fclose(fp); return; } m_error = CreateImage(raw, st.st_size); fclose(fp); OutputError(filename); } PixmapImage::PixmapImage(char** data) { m_error = CreatePixmap(data); } PixmapImage::PixmapImage(char* raw, int len) { m_error = CreateImage(raw, len); } // ~BlImage is not executed when using Imlib PixmapImage::~PixmapImage() { } int PixmapImage::CreateImage(char* raw, int len) { char** data; int error; data = ParseXpmData(raw, len); if (data == NULL) return IMG_DATA_ERROR; error = CreatePixmap(data); for (int i = 0; data[i] != NULL; i++) delete data[i]; delete [] data; return error; } int PixmapImage::CreatePixmap(char** data) { XpmAttributes attr; int error; attr.valuemask = XpmColormap | XpmDepth; attr.colormap = DefaultColormap(display, screen); attr.depth = DefaultDepth(display, screen); error = XpmCreatePixmapFromData(display, root, data, &m_pix, &m_mask, &attr); if (error == XpmSuccess || error == XpmColorError) { XGCValues gcv; gcv.clip_mask = m_mask; m_gc = XCreateGC(display, root, GCClipMask, &gcv); m_size = Dim(attr.width, attr.height); return 0; } switch (error) { case XpmColorFailed: return IMG_COLOR_ERROR; case XpmNoMemory: return IMG_MEMORY_ERROR; default: return IMG_UNKNOWN_ERROR; } } char** PixmapImage::ParseXpmData(char* raw, int len) { char* ptr; int width, height, num_colors, chars_per_pixel; char** data; int i, dlen; // parse pixmap information if ((ptr = GetNextData(raw, len)) != NULL) { if (sscanf(ptr, "%d %d %d %d", &width, &height, &num_colors, &chars_per_pixel) != 4) return NULL; } else return NULL; // allocate data buffer data = new char*[1 + num_colors + height + 1]; data[1 + num_colors + height] = NULL; // terminate data[0] = new char[80]; sprintf(data[0], "%d %d %d %d", width, height, num_colors, chars_per_pixel); // parse color data for (i = 1; i < 1 + num_colors; i++) { if ((ptr = GetNextData(raw, len)) != NULL) { data[i] = new char[raw - ptr]; memcpy(data[i], ptr, raw - ptr - 1); data[i][raw - ptr - 1] = '\0'; } else { for (int j = 0; j < i; j++) delete data[j]; delete [] data; return NULL; } } // parse pixel data dlen = width * chars_per_pixel; for (; i < 1 + num_colors + height; i++) { if ((ptr = GetNextData(raw, len)) != NULL) { data[i] = new char[dlen + 1]; memcpy(data[i], ptr, dlen); data[i][dlen] = '\0'; } else { for (int j = 0; j < i; j++) delete data[j]; delete [] data; return NULL; } } return data; } // return the next data enclosed with " char* PixmapImage::GetNextData(char*& raw, int& len) { char* ptr; while (*raw != '\"' && len > 0) { raw++; len--; } raw++; len--; if (len > 0) ptr = raw; else return NULL; while (*raw != '\"' && len > 0) { raw++; len--; } raw++; len--; if (len > 0) return ptr; else return NULL; }