/** * @brief Sets the message for an omsg. */ static void omsg_setMsg( omsg_t *omsg, const char *msg ) { int i, l, n, s, m; glFont *font; /* Clean up after old stuff. */ if (omsg->msg != NULL) { for (i=0; i<omsg->nlines; i++) free( omsg->msg[i] ); free( omsg->msg ); omsg->msg = 0; omsg->nlines = 0; } /* Create data. */ l = strlen( msg ); font = omsg_getFont( omsg->font ); /* First pass size. */ n = 0; m = 0; while (n < l) { s = gl_printWidthForText( font, &msg[n], omsg_center_w ); n += s+1; m++; } /* Avoid zero-length malloc. */ if (m == 0) return; /* Second pass allocate. */ omsg->msg = malloc( m * sizeof(char*) ); omsg->nlines = m; n = 0; m = 0; while (n < l) { s = gl_printWidthForText( font, &msg[n], omsg_center_w ); omsg->msg[m] = malloc( s+1 ); nsnprintf( omsg->msg[m], s+1, "%s", &msg[n] ); m++; n += s+1; } }
/** * @brief Prints a block of text that fits in the dimensions given. * * Positions are based on origin being top-left. * * @param ft_font Font to use. * @param width Maximum width to print to. * @param height Maximum height to print to. * @param bx X position to display text at. * @param by Y position to display text at. * @param c Colour to use (NULL defaults to white). * @param fmt Text to display formatted like printf. * @return 0 on success. * prints text with line breaks included to a maximum width and height preset */ int gl_printTextRaw( const glFont *ft_font, const int width, const int height, double bx, double by, const glColour* c, const char *text ) { int p, s; double x,y; size_t i, ret; uint32_t ch; if (ft_font == NULL) ft_font = &gl_defFont; glFontStash *stsh = gl_fontGetStash( ft_font ); x = bx; y = by + height - (double)stsh->h; /* y is top left corner */ /* Clears restoration. */ gl_printRestoreClear(); i = 0; s = 0; p = 0; /* where we last drew up to */ while (y - by > -1e-5) { ret = p + gl_printWidthForText( ft_font, &text[p], width ); /* Must restore stuff. */ gl_printRestoreLast(); /* Render it. */ gl_fontRenderStart(stsh, x, y, c); for (i=p; i<ret; ) { ch = u8_nextchar( text, &i); s = gl_fontRenderGlyph( stsh, ch, c, s ); } gl_fontRenderEnd(); if (ch == '\0') break; p = i; if ((text[p] == '\n') || (text[p] == ' ')) p++; /* Skip "empty char". */ y -= 1.5*(double)stsh->h; /* move position down */ } return 0; }
/** * @brief Creates a news widget. * * @param wid Window to create news widget on. * @param x X position of the widget to create. * @param y Y position of the widget to create. * @param w Width of the widget. * @param h Height of the widget. */ void news_widget( unsigned int wid, int x, int y, int w, int h ) { int i, p, len; char buf[4096]; /* Sane defaults. */ news_pos = h/3; news_tick = SDL_GetTicks(); /* Clean news lines. */ news_cleanLines(); /* Load up the news in a string. */ p = 0; for (i=0; i<news_nbuf; i++) { p += snprintf( &buf[p], 2048-p, "%s\n\n" "%s\n\n\n\n" , news_buf[i].title, news_buf[i].desc ); } len = p; /* Now load up the text. */ p = 0; news_nlines = 0; while (p < len) { /* Get the length. */ i = gl_printWidthForText( NULL, &buf[p], w-40 ); /* Copy the line. */ if (news_nlines+1 > news_mlines) { news_mlines += 128; news_lines = realloc( news_lines, sizeof(char*) * news_mlines ); } news_lines[news_nlines] = malloc( i + 1 ); strncpy( news_lines[news_nlines], &buf[p], i ); news_lines[news_nlines][i] = '\0'; p += i + 1; /* Move pointer. */ news_nlines++; /* New line. */ } /* Create the custom widget. */ window_addCust( wid, x, y, w, h, "cstNews", 1, news_render, news_mouse, NULL ); }
/** * @brief Loads the intro stuff. */ static int intro_load( const char *text ) { uint32_t intro_size; char *intro_buf; int i, p, n; int mem; /* Load text. */ intro_buf = ndata_read( text, &intro_size ); intro_length = intro_size; /* Length aproximation. */ /* Create intro font. */ gl_fontInit( &intro_font, NULL, INTRO_FONT_SIZE ); /* Load lines. */ p = 0; n = 0; mem = 0; while ((uint32_t)p < intro_size) { /* Get the length. */ i = gl_printWidthForText( &intro_font, &intro_buf[p], SCREEN_W - 200. ); /* Copy the line. */ if (n+1 > mem) { mem += 128; intro_lines = realloc( intro_lines, sizeof(char*) * mem ); } intro_lines[n] = malloc( i + 1 ); strncpy( intro_lines[n], &intro_buf[p], i ); intro_lines[n][i] = '\0'; p += i + 1; /* Move pointer. */ n++; /* New line. */ } /* Clean up. */ free(intro_buf); intro_nlines = n; return 0; }
/** * @brief Gets the height of a non-formatted string. * * Does not display the text on screen. * * @param ft_font Font to use (NULL defaults to gl_defFont). * @param width Width to jump to next line once reached. * @param fmt Text to get the height of in printf format. * @return The height of the text. */ int gl_printHeightRaw( const glFont *ft_font, const int width, const char *text ) { int i, p; double y; if (ft_font == NULL) ft_font = &gl_defFont; /* Check 0 length strings. */ if (text[0] == '\0') return 0; y = 0.; p = 0; do { i = gl_printWidthForText( ft_font, &text[p], width ); p += i + 1; y += 1.5*(double)ft_font->h; /* move position down */ } while (text[p-1] != '\0'); return (int) (y - 0.5*(double)ft_font->h); }
/** * @brief Creates an on-screen display. * * @param title Title of the display. * @param nitems Number of items in the display. * @param items Items in the display. * @return ID of newly created OSD. */ unsigned int osd_create( const char *title, int nitems, const char **items, int priority ) { int i, j, n, m, l, s, w, t, id; OSD_t *osd; /* Create. */ if (osd_list == NULL) osd_list = array_create( OSD_t ); osd = &array_grow( &osd_list ); memset( osd, 0, sizeof(OSD_t) ); osd->id = ++osd_idgen; osd->active = 0; /* Copy text. */ osd->title = strdup(title); osd->priority = priority; osd->msg = malloc( sizeof(char*) * nitems ); osd->items = malloc( sizeof(OSDmsg_s) * nitems ); osd->nitems = nitems; for (i=0; i<osd->nitems; i++) { osd->msg[i] = strdup( items[i] ); l = strlen(osd->msg[i]); /* Message length. */ n = 0; /* Text position. */ j = 0; /* Lines. */ m = 0; /* Allocated Memory. */ t = 0; /* Tabbed? */ osd->items[i].chunks = NULL; w = osd_w-osd_hyphenLen; while (n < l) { /* Test if tabbed. */ if (j==0) { if (items[i][n] == '\t') { t = 1; w = osd_w - osd_tabLen; } else { t = 0; w = osd_w - osd_hyphenLen; } } /* Get text size. */ s = gl_printWidthForText( &gl_smallFont, &items[i][n], w ); if ((j==0) && (t==1)) w -= osd_hyphenLen; if (j+1 > m) { if (m==0) m = 32; else m *= 2; osd->items[i].chunks = realloc( osd->items[i].chunks, m * sizeof(char*)); } /* Copy text over. */ if (j==0) { if (t==1) { osd->items[i].chunks[j] = malloc(s+4); nsnprintf( osd->items[i].chunks[j], s+4, " %s", &items[i][n+1] ); } else { osd->items[i].chunks[j] = malloc(s+3); nsnprintf( osd->items[i].chunks[j], s+3, "- %s", &items[i][n] ); } } else if (t==1) { osd->items[i].chunks[j] = malloc(s+4); nsnprintf( osd->items[i].chunks[j], s+4, " %s", &items[i][n] ); } else { osd->items[i].chunks[j] = malloc(s+1); nsnprintf( osd->items[i].chunks[j], s+1, "%s", &items[i][n] ); } /* Go to next line. */ n += s + 1; j++; } osd->items[i].nchunks = j; } /* Sort them buggers. */ id = osd->id; /* WE MUST SAVE THE ID BEFORE WE SORT. Or we get stuck with an invalid osd pointer. */ osd_sort(); /* Recalculate dimensions. */ osd_calcDimensions(); return id; }
/** * @brief Loads the intro stuff. */ static int intro_load( const char *text ) { uint32_t intro_size; char *intro_buf; char img_src[128]; /* path to image to be displayed alongside text. */ int length; int i, p, n; int mem; has_side_gfx = 0; /* Load text. */ intro_buf = ndata_read( text, &intro_size ); intro_length = intro_size; /* Length aproximation. */ /* Create intro font. */ gl_fontInit( &intro_font, "dat/mono.ttf", INTRO_FONT_SIZE ); /* Load lines. */ p = 0; n = 0; mem = 0; while ((uint32_t)p < intro_size) { /* Copy the line. */ if (n+1 > mem) { mem += 128; intro_lines = realloc( intro_lines, sizeof(char*) * mem ); } if ( intro_buf[p] == '[' /* Don't do sscanf for every line! */ && sscanf( &intro_buf[p], "[fadein %s", img_src ) == 1 ) { /* an image to appear next to text. */ /* Get the length. */ for (i = 0; intro_buf[p + i] != '\n' && intro_buf[p + i] != '\0'; ++i); length = strlen( img_src ); intro_lines[n] = malloc( length + 2 ); intro_lines[n][0] = 'i'; strncpy( &intro_lines[n][1], img_src, length ); intro_lines[n][length] = '\0'; /* Mark that there are graphics. */ has_side_gfx = 1; } else if ( intro_buf[p] == '[' /* Don't do strncmp for every line! */ && strncmp( &intro_buf[p], "[fadeout]", 9 ) == 0 ) { /* fade out the image next to the text. */ for (i = 0; intro_buf[p + i] != '\n' && intro_buf[p + i] != '\0'; ++i); intro_lines[n] = malloc( 2 ); intro_lines[n][0] = 'o'; intro_lines[n][1] = '\0'; /* not strictly necessary, but safe. */ } else { /* plain old text. */ /* Get the length. */ i = gl_printWidthForText( &intro_font, &intro_buf[p], SCREEN_W - 500. ); intro_lines[n] = malloc( i + 2 ); intro_lines[n][0] = 't'; strncpy( &intro_lines[n][1], &intro_buf[p], i ); intro_lines[n][i+1] = '\0'; } p += i + 1; /* Move pointer. */ n++; /* New line. */ } /* Clean up. */ free(intro_buf); intro_nlines = n; return 0; }
/** * @brief Creates an on-screen display. * * @param title Title of the display. * @param nitems Number of items in the display. * @param items Items in the display. * @return ID of newly created OSD. */ unsigned int osd_create( const char *title, int nitems, const char **items, int priority ) { int i, j, n, m, l, s, w, t; OSD_t *osd, *ll; /* Create. */ osd = calloc( 1, sizeof(OSD_t) ); osd->next = NULL; osd->id = ++osd_idgen; osd->active = 0; /* Copy text. */ osd->title = strdup(title); osd->priority = priority; osd->msg = malloc( sizeof(char*) * nitems ); osd->items = malloc( sizeof(OSDmsg_s) * nitems ); osd->nitems = nitems; for (i=0; i<osd->nitems; i++) { osd->msg[i] = strdup( items[i] ); l = strlen(osd->msg[i]); /* Message length. */ n = 0; /* Text position. */ j = 0; /* Lines. */ m = 0; /* Allocated Memory. */ t = 0; /* Tabbed? */ osd->items[i].chunks = NULL; w = osd_w-osd_hyphenLen; while (n < l) { /* Test if tabbed. */ if (j==0) { if (items[i][n] == '\t') { t = 1; w = osd_w - osd_tabLen; } else { t = 0; w = osd_w - osd_hyphenLen; } } /* Get text size. */ s = gl_printWidthForText( &gl_smallFont, &items[i][n], w ); if ((j==0) && (t==1)) w -= osd_hyphenLen; if (j+1 > m) { m += 32; osd->items[i].chunks = realloc( osd->items[i].chunks, m * sizeof(char*)); } /* Copy text over. */ if (j==0) { if (t==1) { osd->items[i].chunks[j] = malloc(s+4); snprintf( osd->items[i].chunks[j], s+4, " %s", &items[i][n+1] ); } else { osd->items[i].chunks[j] = malloc(s+3); snprintf( osd->items[i].chunks[j], s+3, "- %s", &items[i][n] ); } } else if (t==1) { osd->items[i].chunks[j] = malloc(s+4); snprintf( osd->items[i].chunks[j], s+4, " %s", &items[i][n] ); } else { osd->items[i].chunks[j] = malloc(s+1); snprintf( osd->items[i].chunks[j], s+1, "%s", &items[i][n] ); } /* Go to next line. */ n += s + 1; j++; } osd->items[i].nchunks = j; } /* Append to linked list. */ if (osd_list == NULL) osd_list = osd; else { for (ll = osd_list; ll->next != NULL; ll = ll->next) { if (ll->next->priority > priority) { osd->next = ll->next; break; } } ll->next = osd; } /* Recalculate dimensions. */ osd_calcDimensions(); return osd->id; }