LCOV - code coverage report
Current view: top level - gdraw - gdrawerror.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 11 136 8.1 %
Date: 2017-08-04 Functions: 1 8 12.5 %

          Line data    Source code
       1             : /* Copyright (C) 2000-2012 by George Williams */
       2             : /*
       3             :  * Redistribution and use in source and binary forms, with or without
       4             :  * modification, are permitted provided that the following conditions are met:
       5             : 
       6             :  * Redistributions of source code must retain the above copyright notice, this
       7             :  * list of conditions and the following disclaimer.
       8             : 
       9             :  * Redistributions in binary form must reproduce the above copyright notice,
      10             :  * this list of conditions and the following disclaimer in the documentation
      11             :  * and/or other materials provided with the distribution.
      12             : 
      13             :  * The name of the author may not be used to endorse or promote products
      14             :  * derived from this software without specific prior written permission.
      15             : 
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      17             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      18             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      19             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      20             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      21             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      22             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      23             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      24             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      25             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : 
      28             : #define _GNU_SOURCE
      29             : // GNU stdio does not enable vasprintf if we fail to define this.
      30             : #include <stdio.h>
      31             : #include <string.h>
      32             : #include <stdarg.h>
      33             : 
      34             : #include "gdrawP.h"
      35             : #include "ustring.h"
      36             : 
      37             : /* Preallocate an error dialog so that we can pop it up if things go really bad*/
      38             : /*  ie. if memory gets munched somehow */
      39             : 
      40             : #define ERR_LINE_MAX    20
      41             : static GWindow error;
      42             : enum err_type { et_info, et_warn, et_error, et_fatal };
      43             : static struct errinfo {
      44             :     unichar_t *lines[ERR_LINE_MAX];
      45             :     unsigned int dismissed: 1;
      46             :     int width;
      47             :     enum err_type err_type;
      48             : } errinfo;
      49             : 
      50           0 : static int e_h(GWindow gw, GEvent *event) {
      51             :     int line;
      52             :     int x,len, max_len;
      53             :     GRect r;
      54             :     static unichar_t ok[] = { 'O', 'K', '\0' };
      55             : 
      56           0 :     if ( event->type == et_expose ) {
      57           0 :         max_len = 0;
      58           0 :         for ( line = 0; line<ERR_LINE_MAX && errinfo.lines[line]!=NULL; ++line ) {
      59           0 :             len = GDrawGetTextWidth(gw,errinfo.lines[line],-1);
      60           0 :             if ( len>max_len ) max_len = len;
      61             :         }
      62           0 :         x = (errinfo.width-max_len)/2;
      63           0 :         for ( line = 0; line<ERR_LINE_MAX && errinfo.lines[line]!=NULL; ++line )
      64           0 :             GDrawDrawText(gw,x, 10+10+15*line, errinfo.lines[line],-1,0x000000);
      65             : 
      66           0 :         x = (errinfo.width-(len = GDrawGetTextWidth(gw,ok,2)))/2;
      67           0 :         r.x = x-10; r.y = 25+15*line; r.width = len+20; r.height = 18;
      68           0 :         GDrawFillRect(gw,&r,0xffffff);
      69           0 :         GDrawDrawRect(gw,&r,0x000000);
      70           0 :         GDrawDrawText(gw,x,r.y+13,ok,2,0x000000);
      71           0 :     } else if ( event->type==et_char ) {
      72           0 :         if ( event->u.chr.chars[0]=='\r' || event->u.chr.chars[0]=='\33' )
      73           0 :             errinfo.dismissed = true;
      74           0 :     } else if ( event->type==et_mouseup ) {
      75           0 :         errinfo.dismissed = true;
      76           0 :     } else if ( event->type==et_close ) {
      77           0 :         errinfo.dismissed = true;
      78             :     }
      79           0 : return( 1 );
      80             : }
      81             : 
      82           0 : static void RunError() {
      83           0 :     errinfo.dismissed = false;
      84           0 :     GDrawSetVisible(error,true);
      85           0 :     while ( !errinfo.dismissed )
      86           0 :         GDrawProcessOneEvent(NULL);
      87           0 :     GDrawSetVisible(error,false);
      88           0 :     GDrawSync(NULL);
      89           0 :     GDrawProcessPendingEvents(NULL);
      90           0 : }
      91             : 
      92           0 : static void ProcessText(unichar_t *ubuf,char *buf, enum err_type et) {
      93           0 :     int max_len = 60, len;
      94             :     char *pt, *ept, *last_space;
      95           0 :     unichar_t *ue = ubuf;
      96           0 :     int line=0;
      97             : 
      98           0 :     pt = buf;
      99           0 :     for ( line=0; line<ERR_LINE_MAX && *pt; ++line ) {
     100           0 :         last_space = NULL;
     101           0 :         for ( ept = pt; *ept!='\n' && *ept!='\0' && ept-pt<max_len; ++ept )
     102           0 :             if ( *ept==' ' )
     103           0 :                 last_space = ept;
     104           0 :         if ( *ept!='\n' && *ept!='\0' && last_space!=NULL )
     105           0 :             ept = last_space;
     106           0 :         errinfo.lines[line] = def2u_strncpy(ue,pt,ept-pt);
     107           0 :         ue[ept-pt] = '\0'; ue += (ept+1-pt);
     108           0 :         if ( *ept=='\n' || *ept==' ' ) ++ept;
     109           0 :         pt = ept;
     110             :     }
     111           0 :     for ( ; line<ERR_LINE_MAX ; ++line )
     112           0 :         errinfo.lines[line] = NULL;
     113           0 :     errinfo.err_type = et;
     114             : 
     115           0 :     max_len = 0;
     116           0 :     for ( line = 0; line<ERR_LINE_MAX && errinfo.lines[line]!=NULL; ++line ) {
     117           0 :         len = GDrawGetTextWidth(error,errinfo.lines[line],-1);
     118           0 :         if ( len>max_len ) max_len = len;
     119             :     }
     120           0 :     errinfo.width = max_len+30;
     121           0 :     GDrawResize(error,max_len+30,15*line+50);
     122           0 : }
     123             : 
     124             : GDisplay *global_gd;
     125             : 
     126           0 : void _GDraw_InitError(GDisplay *gd) {
     127             :     GRect screen, pos;
     128             :     static unichar_t title[]= { 'E', 'r', 'r', 'o', 'r', '\0' };
     129             :     static unichar_t courier[] = { 'c', 'o', 'u', 'r', 'i', 'e', 'r', '\0' };
     130             :     static GDisplay *static_gd;
     131             :     GWindowAttrs wattrs;
     132             :     FontRequest rq;
     133             : 
     134           0 :     if ( gd!=NULL )
     135           0 :         static_gd = gd;
     136             :     else
     137           0 :         screen_display = gd = static_gd;
     138             : 
     139           0 :     global_gd = static_gd;
     140             : 
     141           0 :     if ( gd==NULL )
     142           0 : return;
     143             : 
     144           0 :     if ( error != NULL )
     145           0 : return;
     146           0 :     GDrawGetSize(GDrawGetRoot(gd),&screen);
     147             : 
     148           0 :     memset(&wattrs,0,sizeof(wattrs));
     149           0 :     wattrs.mask = wam_events|wam_positioned|wam_cursor|wam_wtitle|wam_backcol|
     150             :             wam_restrict|wam_redirect|wam_isdlg;
     151           0 :     wattrs.event_masks = -1;
     152           0 :     wattrs.positioned = 1;
     153           0 :     wattrs.cursor = ct_pointer;
     154           0 :     wattrs.window_title = title;
     155           0 :     wattrs.background_color = 0xbbbbbb;
     156           0 :     wattrs.restrict_input_to_me = true;
     157           0 :     wattrs.redirect_chars_to_me = true;
     158           0 :     wattrs.is_dlg = true;
     159           0 :     pos.width = 300; pos.height = 180;
     160           0 :     pos.x = (screen.width-pos.width)/2;
     161           0 :     pos.y = (screen.width-pos.width)/3;
     162           0 :     errinfo.width = pos.width;
     163             : 
     164           0 :     error = GDrawCreateTopWindow(gd,&pos,e_h,NULL,&wattrs);
     165             : 
     166           0 :     memset(&rq,0,sizeof(rq));
     167           0 :     rq.family_name = courier;
     168           0 :     rq.point_size = -12;
     169           0 :     rq.weight = 400;
     170           0 :     rq.style = 0;
     171           0 :     GDrawAttachFont(error,&rq);
     172             : }
     173             : 
     174           1 : void GDrawIError(const char *fmt,...) {
     175             :   // GDrawIErrorRun was the previous version of this function.
     176             :   // This new function intercepts the calls and stashes them for future processing.
     177             :   // This avoids stack overflows in certain cases.
     178           1 :   GDisplay * gd = global_gd;
     179           1 :   char * buffer = NULL;
     180             :   va_list ap;
     181           1 :   va_start(ap, fmt);
     182           1 :   int preret = vasprintf(&buffer, fmt, ap);
     183           1 :   va_end(ap);
     184           2 :   if (preret < 0 ) return;
     185           1 :   if (buffer != NULL ) {
     186           1 :     if ( gd==NULL ) {
     187           1 :       fprintf(stderr, "%s", buffer); // If there is no display, we write to stderr.
     188             :     } else {
     189           0 :       if ((gd->err_flag) && (gd->err_report != NULL)) {
     190           0 :         if (strlen(gd->err_report) + strlen(buffer) + 1 < 2048) {
     191             :           // If there is an existing error message, we concatenate if there is space.
     192             :           char * tmp;
     193           0 :           asprintf(&tmp, "%s%s\n", gd->err_report, buffer);
     194           0 :           free(gd->err_report); gd->err_report = tmp;
     195             :         }
     196             :       } else {
     197             :         // If there is no existing error message, we copy to the right spot.
     198           0 :         asprintf(&gd->err_report, "%s\n", buffer);
     199             :       }
     200           0 :       gd->err_flag |= 1;
     201             :     }
     202             :   }
     203           1 :   free(buffer); buffer = NULL;
     204             : }
     205             : 
     206           0 : void GDrawIErrorRun(const char *fmt,...) {
     207             :     char buf[1025]; unichar_t ubuf[1025];
     208             :     va_list ap;
     209             : 
     210           0 :     strcpy(buf,"Internal Error:\n");
     211           0 :     va_start(ap, fmt);
     212           0 :     vsnprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), fmt, ap);
     213           0 :     va_end(ap);
     214           0 :     fprintf( stderr, "%s\n", buf );
     215           0 :     _GDraw_InitError(NULL);
     216           0 :     if ( error!=NULL ) {
     217           0 :         ProcessText(ubuf,buf,et_error);
     218           0 :         RunError();
     219             :     }
     220           0 : }
     221             : 
     222           0 : void GDrawError(const char *fmt,...) {
     223             :     char buf[1025]; unichar_t ubuf[1025];
     224             :     va_list ap;
     225             : 
     226           0 :     va_start(ap, fmt);
     227           0 :     vsprintf(buf, fmt, ap);
     228           0 :     va_end(ap);
     229           0 :     _GDraw_InitError(NULL);
     230           0 :     if ( error==NULL )
     231           0 :         fprintf( stderr, "%s\n", buf );
     232             :     else {
     233           0 :         ProcessText(ubuf,buf,et_error);
     234           0 :         RunError();
     235             :     }
     236           0 : }
     237             : 
     238           0 : void GDrawFatalError(const char *fmt,...) {
     239             :     char buf[1025]; unichar_t ubuf[1025];
     240             :     va_list ap;
     241             : 
     242           0 :     strcpy(buf,"Fatal Error:\n");
     243           0 :     va_start(ap, fmt);
     244           0 :     vsprintf(buf+strlen(buf), fmt, ap);
     245           0 :     va_end(ap);
     246           0 :         fprintf( stderr, "%s\n", buf );
     247           0 :     if ( error!=NULL ) {
     248           0 :         ProcessText(ubuf,buf,et_fatal);
     249           0 :         RunError();
     250             :     }
     251           0 :     exit(1);
     252             : }

Generated by: LCOV version 1.10