Sat, 14 Nov 2015 17:00:37 +0100
Fixed compiling on a raspberry
/***************************************************************************** * Copyright (C) 2015 * * Michiel Broek <mbroek at mbse dot eu> * * This file is part of the mbsePi-apps emulator * * The gui code is based on the gui from the emulator ARAnyM, * Copyright (c) 2004 Petr Stehlik of ARAnyM dev team * * This progrm 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, or (at your option) any * later version. * * mbsePi-apps 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 mbsePi-apps; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ #include "brewpanel.h" #include "sdlgui.h" #include "sockio.h" #ifdef HAVE_SDL_SDL_H #include "lcdfont10x16.h" static SDL_Surface *pSdlGuiScrn; /* Pointer to the actual main SDL screen surface */ static SDL_Surface *pFontGfx = NULL; /* The LCD font graphics */ static SDL_Surface *pBgSurface; /* Pointer to the application SDL screen surface */ static SDL_Rect dlgrect, bgrect; static int fontwidth, fontheight; /* Width & height of the actual font */ TTF_Font *pFont = NULL; /* TTF font for buttons etc. */ extern int my_shutdown; /*-----------------------------------------------------------------------*/ /* * Load an 1 plane XBM into a 8 planes SDL_Surface. */ static SDL_Surface *SDLGui_LoadXBM(int w, int h, const char *pXbmBits) { SDL_Surface *bitmap; Uint8 *dstbits; const Uint8 *srcbits; int x, y, srcpitch, mask; srcbits = (Uint8 *)pXbmBits; /* Allocate the bitmap */ if ((bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0)) == NULL) { syslog(LOG_NOTICE, "Failed to allocate bitmap: %s", SDL_GetError()); return NULL; } srcpitch = ((w + 7) / 8); dstbits = (Uint8 *)bitmap->pixels; mask = 1; /* Copy the pixels */ for (y = 0 ; y < h ; y++) { for (x = 0 ; x < w ; x++) { dstbits[x] = (srcbits[x / 8] & mask) ? 1 : 0; mask <<= 1; mask |= (mask >> 8); mask &= 0xFF; } dstbits += bitmap->pitch; srcbits += srcpitch; } return bitmap; } /* * Initialize the GUI. */ int SDLGui_Init(void) { char *Pt = NULL; SDL_Color blackWhiteColors[2] = {{255, 255, 255, 0}, {53, 59, 61, 0}}; /* * Initialize the LCD font graphics: */ pFontGfx = SDLGui_LoadXBM(lcdfont10x16_width, lcdfont10x16_height, lcdfont10x16_bits); if (pFontGfx == NULL) { syslog(LOG_NOTICE, "Error: Can not init font graphics!"); return -1; } /* Set color palette of the LCD font graphics: */ SDL_SetColors(pFontGfx, blackWhiteColors, 0, 2); /* Set font color 0 as transparent: */ SDL_SetColorKey(pFontGfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), 0); if (TTF_Init() == -1) { syslog(LOG_NOTICE, "Could not init SDL_ttf"); return -1; } /* * Load TTF font for the dialogs */ Pt = calloc(1024, sizeof(char)); sprintf(Pt, "%s", "/usr/share/fonts/TTF/DejaVuSans.ttf"); if ((pFont = TTF_OpenFont(Pt, 14 )) == NULL) { sprintf(Pt, "%s", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"); if ((pFont = TTF_OpenFont(Pt, 14 )) == NULL) { sprintf(Pt, "%s", "/usr/share/fonts/truetype/freefont/DejaVuSans.ttf"); if ((pFont = TTF_OpenFont(Pt, 14 )) == NULL) { syslog(LOG_NOTICE, "Could not load DejaVuSans.ttf"); return -1; } } } syslog(LOG_NOTICE, "Using ttf font: %s\n", Pt); free(Pt); Pt = NULL; return 0; } /* * Uninitialize the GUI. */ int SDLGui_UnInit(void) { if (pFont) TTF_CloseFont(pFont); pFont = NULL; if (pFontGfx) SDL_FreeSurface(pFontGfx); pFontGfx = NULL; return 0; } /* * Inform the SDL-GUI about the actual SDL_Surface screen pointer and * prepare the font to suit the actual resolution. */ int SDLGui_SetScreen(SDL_Surface *pScrn) { pSdlGuiScrn = pScrn; if (pFontGfx == NULL) { syslog(LOG_NOTICE, "Error: A problem with the font occured!"); return -1; } /* Get the font width and height: */ fontwidth = pFontGfx->w/16; fontheight = pFontGfx->h/16; return 0; } /* * Center a dialog so that it appears in the middle of the screen. * Note: We only store the coordinates in the root box of the dialog, * all other objects in the dialog are positioned relatively to this one. */ void SDLGui_CenterDlg(SGOBJ *dlg) { dlg[0].x = (pSdlGuiScrn->w/1-dlg[0].w)/2; dlg[0].y = (pSdlGuiScrn->h/1-dlg[0].h)/2; } /* * Draw a text string using TTF */ static void SDLGui_TTF(int x, int y, const char *txt) { SDL_Rect offset; SDL_Color textColor = { 0, 0, 0 }; SDL_Surface* message = NULL; message = TTF_RenderText_Solid(pFont, txt, textColor); offset.x = x; offset.y = y; SDL_BlitSurface(message, NULL, pSdlGuiScrn, &offset); SDL_FreeSurface(message); message = NULL; } /* * Draw a dialog TTF text object. */ static void SDLGui_DrawTTF(const SGOBJ *tdlg, int objnum) { int x, y; x = (tdlg[0].x + tdlg[objnum].x); y = (tdlg[0].y + tdlg[objnum].y); SDLGui_TTF(x, y, tdlg[objnum].txt); } /* * Draw the cursor */ void SDLGui_Cursor(int x, int y, int on, int blink) { SDL_Rect dr; Uint32 color = SDL_MapRGB(pSdlGuiScrn->format, 53, 59, 61); if (on) { dr.x = x; dr.y = y + fontheight - 2; dr.w = fontwidth; dr.h = 2; SDL_FillRect(pSdlGuiScrn, &dr, color); SDL_UpdateRect(pSdlGuiScrn, x, y, fontwidth, fontheight); } } /* * Draw a text character */ void SDLGui_Char(int x, int y, Uint8 c, int bLight) { SDL_Rect sr, dr; Uint32 bg; if (bLight) bg = SDL_MapRGB(pSdlGuiScrn->format,156,235, 4); else bg = SDL_MapRGB(pSdlGuiScrn->format, 94,147, 69); sr.x=fontwidth*(c%16); sr.y=fontheight*(c/16); sr.w=fontwidth; sr.h=fontheight; dr.x=x; dr.y=y; dr.w=fontwidth; dr.h=fontheight; SDL_FillRect(pSdlGuiScrn, &dr, bg); SDL_BlitSurface(pFontGfx, &sr, pSdlGuiScrn, &dr); SDL_UpdateRect(pSdlGuiScrn, x, y, fontwidth, fontheight); } /* * Draw a text string. */ static void SDLGui_Text(int x, int y, const char *txt) { int i; Uint8 c; SDL_Rect sr, dr; for (i=0; txt[i]!=0; i++) { c = txt[i] & 0xff; sr.x=fontwidth*(c%16); sr.y=fontheight*(c/16); sr.w=fontwidth; sr.h=fontheight; dr.x=x+i*(fontwidth+2); dr.y=y; dr.w=fontwidth; dr.h=fontheight; SDL_BlitSurface(pFontGfx, &sr, pSdlGuiScrn, &dr); } } /* * Draw a dialog text object. */ static void SDLGui_DrawText(const SGOBJ *tdlg, int objnum) { int x, y; x = (tdlg[0].x + tdlg[objnum].x); y = (tdlg[0].y + tdlg[objnum].y); SDLGui_Text(x, y, tdlg[objnum].txt); } /* * Draw a dialog LCD object. */ static void SDLGui_DrawLCD(const SGOBJ *bdlg, int objnum) { SDL_Rect rect; int x, y, w, h, offset, border = 4; Uint32 bg0 = SDL_MapRGB(pSdlGuiScrn->format, 94,147, 69); Uint32 bg1 = SDL_MapRGB(pSdlGuiScrn->format,156,235, 4); Uint32 bc = SDL_MapRGB(pSdlGuiScrn->format, 32, 32, 32); Uint32 bg; /* * Width and height are given in character columns and rows, * so calculate the display size in pixels. */ w = bdlg[objnum].w * (fontwidth + 2) + 10; h = bdlg[objnum].h * (fontheight + 2) + 4; if (bdlg[objnum].x == -1) { /* * Auto center */ x = (bdlg[0].w - w) / 2; } else { x = bdlg[objnum].x; } y = bdlg[objnum].y; if (objnum > 0) { /* Since the root object is a box, too, */ /* we have to look for it now here and only */ x += bdlg[0].x; /* add its absolute coordinates if we need to */ y += bdlg[0].y; } if (bdlg[objnum].state & SG_SELECTED) { bg = bg1; } else { bg = bg0; } /* The root box should be bigger than the screen, so we disable the offset there: */ if (objnum != 0) offset = border; else offset = 0; /* Draw background: */ rect.x = x; rect.y = y; rect.w = w; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, bg); /* Draw upper border: */ rect.x = x - offset; rect.y = y - offset; rect.w = w + offset + offset; rect.h = border; SDL_FillRect(pSdlGuiScrn, &rect, bc); /* Draw left border: */ rect.x = x - offset; rect.y = y; rect.w = border; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, bc); /* Draw bottom border: */ rect.x = x - offset; rect.y = y + h - border + offset; rect.w = w + offset + offset; rect.h = border; SDL_FillRect(pSdlGuiScrn, &rect, bc); /* Draw right border: */ rect.x = x + w - border + offset; rect.y = y; rect.w = border; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, bc); } /* * Draw a dialog box object. */ static void SDLGui_DrawBox(const SGOBJ *bdlg, int objnum) { SDL_Rect rect; int x, y, w, h, offset, shade = 2; Uint32 grey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192); Uint32 upleftc, downrightc; x = bdlg[objnum].x; y = bdlg[objnum].y; if (objnum > 0) { /* Since the root object is a box, too, */ /* we have to look for it now here and only */ x += bdlg[0].x; /* add its absolute coordinates if we need to */ y += bdlg[0].y; } w = bdlg[objnum].w; h = bdlg[objnum].h; if (bdlg[objnum].state & SG_SELECTED) { upleftc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128); downrightc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255); } else { upleftc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255); downrightc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128); } /* The root box should be bigger than the screen, so we disable the offset there: */ if (objnum != 0) offset = shade; else offset = 0; /* Draw background: */ rect.x = x; rect.y = y; rect.w = w; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, grey); /* Draw upper border: */ rect.x = x; rect.y = y - offset; rect.w = w; rect.h = shade; SDL_FillRect(pSdlGuiScrn, &rect, upleftc); /* Draw left border: */ rect.x = x - offset; rect.y = y; rect.w = shade; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, upleftc); /* Draw bottom border: */ rect.x = x; rect.y = y + h - shade + offset; rect.w = w; rect.h = shade; SDL_FillRect(pSdlGuiScrn, &rect, downrightc); /* Draw right border: */ rect.x = x + w - shade + offset; rect.y = y; rect.w = shade; rect.h = h; SDL_FillRect(pSdlGuiScrn, &rect, downrightc); } /* * Draw a normal button. */ static void SDLGui_DrawButton(const SGOBJ *bdlg, int objnum) { int x, y, w, h; SDLGui_DrawBox(bdlg, objnum); /* * Use bold text and get outer dimensions of the text */ TTF_SetFontStyle(pFont, TTF_STYLE_BOLD); TTF_SizeText(pFont, bdlg[objnum].txt, &w, &h); x = bdlg[0].x + bdlg[objnum].x + (bdlg[objnum].w - w) / 2; y = bdlg[0].y + bdlg[objnum].y + (bdlg[objnum].h - h) / 2; if (bdlg[objnum].state & SG_SELECTED) { x += 1; y += 1; } if ((bdlg[objnum].flags & SG_HIDE) == 0) SDLGui_TTF(x, y, bdlg[objnum].txt); TTF_SetFontStyle(pFont, TTF_STYLE_NORMAL); } /* * Draw a whole dialog. */ void SDLGui_DrawDialog(const SGOBJ *dlg) { int i; for (i = 0; dlg[i].type != -1; i++) { switch (dlg[i].type) { case SGBOX: SDLGui_DrawBox(dlg, i); break; case SGLCD: SDLGui_DrawLCD(dlg, i); break; case SGTEXT: SDLGui_DrawText(dlg, i); break; case SGTTF: SDLGui_DrawTTF(dlg, i); break; case SGBUTTON: SDLGui_DrawButton(dlg, i); break; } } SDL_UpdateRect(pSdlGuiScrn, 0,0,0,0); } /* * Search an object at a certain position. */ static int SDLGui_FindObj(const SGOBJ *dlg, int fx, int fy) { int len, i, ob = -1, xpos, ypos; len = 0; while (dlg[len].type != -1) len++; xpos = fx; ypos = fy; /* Now search for the object: */ for (i = len; i >= 0; i--) { if (xpos >= dlg[0].x + dlg[i].x && ypos >= dlg[0].y + dlg[i].y && xpos < dlg[0].x + dlg[i].x + dlg[i].w && ypos < dlg[0].y + dlg[i].y + dlg[i].h) { ob = i; break; } } return ob; } /* * Search a button with a special flag (e.g. SG_DEFAULT or SG_CANCEL). */ static int SDLGui_SearchFlaggedButton(const SGOBJ *dlg, int flag) { int i = 0; while (dlg[i].type != -1) { if (dlg[i].flags & flag) return i; i++; } return 0; } /* * Show dialog. */ int SDLGui_DoDialogInit(SGOBJ *dlg) { if ((pSdlGuiScrn->h < dlg[0].h) && (pSdlGuiScrn->w < dlg[0].w)) { syslog(LOG_NOTICE, "Screen size too small for dialog!"); return SDLGUI_ERROR; } dlgrect.x = dlg[0].x; dlgrect.y = dlg[0].y; dlgrect.w = dlg[0].w; dlgrect.h = dlg[0].h; bgrect.x = bgrect.y = 0; bgrect.w = dlgrect.w; bgrect.h = dlgrect.h; /* * Save background */ pBgSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, dlgrect.w, dlgrect.h, pSdlGuiScrn->format->BitsPerPixel, pSdlGuiScrn->format->Rmask, pSdlGuiScrn->format->Gmask, pSdlGuiScrn->format->Bmask, pSdlGuiScrn->format->Amask); if (pSdlGuiScrn->format->palette != NULL) { SDL_SetColors(pBgSurface, pSdlGuiScrn->format->palette->colors, 0, pSdlGuiScrn->format->palette->ncolors-1); } if (pBgSurface != NULL) { SDL_BlitSurface(pSdlGuiScrn, &dlgrect, pBgSurface, &bgrect); } else { syslog(LOG_NOTICE, "SDLGUI_DoDialog: CreateRGBSurface failed: %s", SDL_GetError()); } /* (Re-)draw the dialog */ SDLGui_DrawDialog(dlg); return 0; } /* * Process a dialog. Returns the button number that has been pressed */ int SDLGui_DoDialogLoop(SGOBJ *dlg) { int obj = 0, oldbutton = 0, retbutton = 0, b, i, j; SDL_Event sdlEvent; /* * Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */ SDL_PumpEvents(); b = SDL_GetMouseState(&i, &j); obj = SDLGui_FindObj(dlg, i, j); if (obj > 0 && (dlg[obj].flags & SG_TOUCHEXIT) ) { oldbutton = obj; if (b & SDL_BUTTON(1)) { dlg[obj].state |= SG_SELECTED; retbutton = obj; } } /* The main loop */ while (retbutton == 0 && !my_shutdown) { socket_recv(); if (SDL_PollEvent(&sdlEvent) == 1) { /* Wait for events */ switch (sdlEvent.type) { case SDL_QUIT: retbutton = SDLGUI_QUIT; break; case SDL_MOUSEBUTTONDOWN: if (sdlEvent.button.button != SDL_BUTTON_LEFT) { /* Not left mouse button -> unsupported event */ break; } /* It was the left button: Find the object under the mouse cursor */ obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y); if (obj > 0) { if (dlg[obj].type == SGBUTTON) { dlg[obj].state |= SG_SELECTED; SDLGui_DrawButton(dlg, obj); SDL_UpdateRect(pSdlGuiScrn, dlg[0].x + dlg[obj].x - 2, dlg[0].y + dlg[obj].y - 2, dlg[obj].w + 4, dlg[obj].h + 4); oldbutton=obj; } if ( dlg[obj].flags & SG_TOUCHEXIT ) { dlg[obj].state |= SG_SELECTED; retbutton = obj; } } break; case SDL_MOUSEBUTTONUP: if (sdlEvent.button.button != SDL_BUTTON_LEFT) { /* Not left mouse button -> unsupported event */ break; } /* It was the left button: Find the object under the mouse cursor */ obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y); if (obj > 0) { switch (dlg[obj].type) { case SGBUTTON: if (oldbutton==obj) retbutton=obj; break; } } if (oldbutton > 0) { dlg[oldbutton].state &= ~SG_SELECTED; SDLGui_DrawButton(dlg, oldbutton); SDL_UpdateRect(pSdlGuiScrn, dlg[0].x+dlg[oldbutton].x-2, dlg[0].y+dlg[oldbutton].y-2, dlg[oldbutton].w+4, dlg[oldbutton].h+4); oldbutton = 0; } if (obj >= 0 && (dlg[obj].flags & SG_EXIT)) { retbutton = obj; } break; case SDL_MOUSEMOTION: break; case SDL_KEYDOWN: /* Key pressed */ if (sdlEvent.key.keysym.sym == SDLK_RETURN || sdlEvent.key.keysym.sym == SDLK_KP_ENTER) { retbutton = SDLGui_SearchFlaggedButton(dlg, SG_DEFAULT); } else if (sdlEvent.key.keysym.sym == SDLK_ESCAPE) { retbutton = SDLGui_SearchFlaggedButton(dlg, SG_CANCEL); } break; } } else { SDL_Delay(1); } } if (retbutton == SDLGUI_QUIT) my_shutdown = TRUE; return retbutton; } void SDLGui_DoDialogEnd(void) { /* Restore background */ if (pBgSurface) { SDL_BlitSurface(pBgSurface, &bgrect, pSdlGuiScrn, &dlgrect); SDL_FreeSurface(pBgSurface); } } /* * Initialize a LCD object. Set the coordinates and dimenstions. Return index. */ int SDLGui_LCDinit(SGOBJ *dlg, int *x, int *y, int *w, int *h, int *cols, int *rows, int lcdindex) { int i, index; /* * Search the LCD display */ *x = *y = *w = *h = *cols = *rows = i = index = 0; for (;;) { if (dlg[i].type == -1) { syslog(LOG_NOTICE, "SDLGui_LCDinit() lcdindex=%d not found", lcdindex); return -1; } if (dlg[i].type == SGLCD) { if (index == lcdindex) break; index++; } i++; } fprintf(stdout, "SDLGui_LCDinit=%d LCD=%dx%d %dx%d\n", i, dlg[i].x, dlg[i].y, dlg[i].w, dlg[i].h); *cols = dlg[i].w; *rows = dlg[i].h; *w = dlg[i].w * (fontwidth + 2) + 10; *h = dlg[i].h * (fontheight + 2) + 4; if (dlg[i].x == -1) { *x = (dlg[0].w - *w) / 2; } else { *x = dlg[i].x; } *y = dlg[i].y; return lcdindex; } /* void SDLGui_LCDwrite(SGOBJ *dlg, int x, int y, Uint8 c, int lcdindex) { int i, index; fprintf(stdout, "SDLGui_LCDwrite( , %d, %d, %c, %d)\n", x, y, c, lcdindex); i = index = 0; for (;;) { if (dlg[i].type == -1) { syslog(LOG_NOTICE, "SDLGui_LCDwrite() lcdindex=%d not found", lcdindex); return; } if (dlg[i].type == SGLCD) { if (index == lcdindex) break; index++; } i++; } fprintf(stdout, "SDLGui_LCDwrite i=%d LCD=%dx%d\n", i, dlg[i].w, dlg[i].h); } */ #endif