LCOV - code coverage report
Current view: top level - fontforgeexe - uiutil.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 30 400 7.5 %
Date: 2017-08-04 Functions: 3 26 11.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             : #include "fontforgeui.h"
      28             : #include <gfile.h>
      29             : #include <stdarg.h>
      30             : #include <unistd.h>
      31             : #include <utype.h>
      32             : #include <ustring.h>
      33             : #include <sys/time.h>
      34             : #include <gkeysym.h>
      35             : 
      36             : extern GBox _ggadget_Default_Box;
      37             : #define ACTIVE_BORDER   (_ggadget_Default_Box.active_border)
      38             : #define MAIN_FOREGROUND (_ggadget_Default_Box.main_foreground)
      39             : 
      40             : #if __CygWin
      41             : extern void cygwin_conv_to_full_posix_path(const char *win,char *unx);
      42             : extern void cygwin_conv_to_full_win32_path(const char *unx,char *win);
      43             : #endif
      44             : 
      45             : static char browser[1025];
      46             : 
      47           0 : static void findbrowser(void) {
      48             : /* Find a browser to use so that help messages can be displayed */
      49             : 
      50             : /* Both xdg-open and htmlview are not browsers per se, but browser dispatchers*/
      51             : /*  which try to figure out what browser the user intents. It seems no one */
      52             : /*  uses (understands?) environment variables any more, so BROWSER is a bit */
      53             : /*  old-fashioned */
      54             :     static char *stdbrowsers[] = { "xdg-open", "x-www-browser", "htmlview",
      55             : #if __Mac
      56             :         "safari",
      57             : #endif
      58             :         "firefox", "mozilla", "seamonkey", "iceweasel", "opera", "konqueror", "google-chrome",
      59             :         "galeon", "kfmclient", "netscape", "mosaic", /*"grail",*/ "lynx",
      60             :         NULL };
      61             :     int i;
      62             :     char *path;
      63             : 
      64           0 :     if ( getenv("BROWSER")!=NULL ) {
      65           0 :         strncpy(browser,getenv("BROWSER"),sizeof(browser));
      66           0 :     browser[sizeof(browser)-1] = '\0';
      67           0 :         if ( strcmp(browser,"kde")==0 || strcmp(browser,"kfm")==0 ||
      68           0 :                 strcmp(browser,"konqueror")==0 || strcmp(browser,"kfmclient")==0 )
      69           0 :             strcpy(browser,"kfmclient openURL");
      70           0 : return;
      71             :     }
      72           0 :     for ( i=0; stdbrowsers[i]!=NULL; ++i ) {
      73           0 :         if ( (path=_GFile_find_program_dir(stdbrowsers[i]))!=NULL ) {
      74           0 :             if ( strcmp(stdbrowsers[i],"kfmclient")==0 )
      75           0 :                 strcpy(browser,"kfmclient openURL");
      76             :             else
      77           0 :                 strcpy(browser,stdbrowsers[i]);
      78           0 :             free(path);
      79           0 : return;
      80             :         }
      81             :     }
      82             : #if __Mac
      83             :     strcpy(browser,"open");   /* thanks to riggle */
      84             : #endif
      85             : }
      86             : 
      87           0 : static int SupportedLocale(char *fullspec,char *locale) {
      88             : /* If there's additional help files written for other languages, then check */
      89             : /* to see if this local matches the additional help message language. If so */
      90             : /* then report back that there's another language available to use for help */
      91             : /* NOTE: If Docs are not maintained very well, maybe comment-out lang here. */
      92             :     int i;
      93             :     /* list languages in specific to generic order, ie: en_CA, en_GB, en... */
      94             :     static char *supported[] = { "de","ja", NULL }; /* other html lang list */
      95             : 
      96           0 :     for ( i=0; supported[i]!=NULL; ++i ) {
      97           0 :         if ( strcmp(locale,supported[i])==0 ) {
      98           0 :             strcat(fullspec,supported[i]);
      99           0 :             strcat(fullspec,"/");
     100           0 :             return( true );
     101             :         }
     102             :     }
     103           0 :     return( false );
     104             : }
     105             : 
     106           0 : static void AppendSupportedLocale(char *fullspec) {
     107             : /* Add Browser HELP for this local if there's more html docs for this local */
     108             : 
     109             :     /* KANOU has provided a japanese translation of the docs */
     110             :     /* Edward Lee is working on traditional chinese docs */
     111           0 :     const char *loc = getenv("LC_ALL");
     112             :     char buffer[40], *pt;
     113             : 
     114           0 :     if ( loc==NULL ) loc = getenv("LC_CTYPE");
     115           0 :     if ( loc==NULL ) loc = getenv("LANG");
     116           0 :     if ( loc==NULL ) loc = getenv("LC_MESSAGES");
     117           0 :     if ( loc==NULL )
     118           0 :         return;
     119             : 
     120             :     /* first, try checking entire string */
     121           0 :     strncpy(buffer,loc,sizeof(buffer));
     122           0 :     buffer[sizeof(buffer)-1] = '\0';
     123           0 :     if ( SupportedLocale(fullspec,buffer) )
     124           0 :         return;
     125             : 
     126             :     /* parse possible suffixes, such as .UTF-8, then try again */
     127           0 :     if ( (pt=strchr(buffer,'.'))!=NULL ) {
     128           0 :         *pt = '\0';
     129           0 :         if ( SupportedLocale(fullspec,buffer) )
     130           0 :             return;
     131             :     }
     132             : 
     133             :     /* parse possible suffixes such as _CA, _GB, and try again */
     134           0 :     if ( (pt=strchr(buffer,'_'))!=NULL ) {
     135           0 :         *pt = '\0';
     136           0 :         if ( SupportedLocale(fullspec,buffer) )
     137           0 :             return;
     138             :     }
     139             : }
     140             : 
     141             : #ifdef _WIN32
     142             : #include <gresource.h>
     143             : #include <windows.h>
     144             : void help(char *file) {
     145             :     if(file){
     146             :         int   len     = strlen(file);
     147             :         char* p_file  = (char*) malloc(len+1);
     148             :         char* p_uri   = (char*) malloc(len+1024);
     149             :         char* p_param = NULL;
     150             : 
     151             :         strcpy(p_file,  file);
     152             : 
     153             :         {
     154             :             char* delim = strrchr(p_file, '#');
     155             :             if(delim){
     156             :                 p_param = (char*) malloc(len+1);
     157             :                 strcpy(p_param, delim);
     158             :                 *delim = '\0';
     159             :             }
     160             :         }
     161             : 
     162             :         strcpy(p_uri, p_file);
     163             : 
     164             :         if(! GFileIsAbsolute(p_uri)){
     165             :             char* p_helpdir = (char*) malloc(1024);
     166             : 
     167             :             #if __CygWin
     168             :             {   /* cygwin */
     169             :                 #if defined(DOCDIR)
     170             :                 strncpy( p_helpdir, DOCDIR "/", 1024 );
     171             :                 #elif defined(SHAREDIR)
     172             :                 strncpy( p_helpdir, SHAREDIR "/doc/fontforge/", 1024 );
     173             :                 #else
     174             :                 strncpy( p_helpdir, "/usr/local/share/doc/fontforge/", 1024 );
     175             :                 #endif
     176             :             }
     177             :             #else
     178             :             {   /* mingw */
     179             :                 strcpy( p_helpdir, GResourceProgramDir );
     180             :                 strcat( p_helpdir, "/doc/fontforge/");
     181             :             }
     182             :             #endif
     183             : 
     184             :             /* /usr/share/fontforge/doc/ja/file */
     185             :             strcpy(p_uri, p_helpdir);
     186             :             AppendSupportedLocale(p_uri);
     187             :             strcat(p_uri, p_file);
     188             : 
     189             :             if(!GFileReadable(p_uri)){
     190             :                 strcpy(p_uri, p_helpdir);
     191             :                 strcat(p_uri, p_file);
     192             : 
     193             :                 if(!GFileReadable(p_uri)){
     194             :                     strcpy(p_uri, "http://fontforge.org/");
     195             :                     /* AppendSupportedLocale(p_uri); */
     196             :                     strcat(p_uri, p_file);
     197             :                 }
     198             :             }
     199             :             free(p_helpdir);
     200             :         }
     201             : 
     202             :         #if __CygWin
     203             :         if( strncmp(p_uri, "http:", 5) != 0 ){
     204             :             char*  temp = (char*) malloc(1024);
     205             :             cygwin_conv_to_full_win32_path(p_uri, temp);
     206             :             free(p_uri);
     207             :             p_uri = temp;
     208             :         }
     209             :         #endif
     210             : 
     211             :         if(p_param){
     212             :             strcat(p_uri, p_param);
     213             :             free(p_param);
     214             :         }
     215             : 
     216             :         /* using default browser */
     217             :         ShellExecute(NULL, "open", p_uri, NULL, NULL, SW_SHOWDEFAULT);
     218             : 
     219             :         free(p_uri);
     220             :         free(p_file);
     221             :     }
     222             : }
     223             : #else
     224             : 
     225           0 : void help(char *file) {
     226             :     char fullspec[PATH_MAX], *temp, *pt;
     227             : 
     228           0 :     if ( browser[0]=='\0' )
     229           0 :         findbrowser();
     230           0 :     if ( browser[0]=='\0' ) {
     231           0 :         gwwv_post_error(_("No Browser"),_("Could not find a browser. Set the BROWSER environment variable to point to one"));
     232           0 : return;
     233             :     }
     234             : 
     235           0 :     if ( strstr(file,"http://")==NULL ) {
     236           0 :         memset(fullspec,0,sizeof(fullspec));
     237           0 :         if ( ! GFileIsAbsolute(file) )
     238           0 :             snprintf(fullspec, PATH_MAX, "%s", getHelpDir());
     239           0 :         strcat(fullspec,file);
     240           0 :         if (( pt = strrchr(fullspec,'#') )!=NULL ) *pt ='\0';
     241           0 :         if ( !GFileReadable( fullspec )) {
     242           0 :             if ( *file!='/' ) {
     243           0 :                 strcpy(fullspec,"/usr/share/doc/fontforge/");
     244           0 :                 strcat(fullspec,file);
     245           0 :                 if (( pt = strrchr(fullspec,'#') )!=NULL ) *pt ='\0';
     246             :             }
     247             :         }
     248           0 :         if ( !GFileReadable( fullspec )) {
     249           0 :             strcpy(fullspec,"http://fontforge.sf.net/");
     250           0 :             AppendSupportedLocale(fullspec);
     251           0 :             strcat(fullspec,file);
     252           0 :         } else if ( pt!=NULL )
     253           0 :             *pt = '#';
     254             :     } else
     255           0 :         strncpy(fullspec,file,sizeof(fullspec));
     256             : #if __Mac
     257             :     if ( strcmp(browser,"open")==0 )
     258             :         /* open doesn't want "file:" prepended */;
     259             :     else
     260             : #endif
     261           0 :     if ( strstr(fullspec,":/")==NULL ) {
     262           0 :         if ( (temp=malloc(strlen(fullspec)+strlen("file:")+20))==NULL )
     263           0 :             return;
     264           0 :         sprintf(temp,"file:%s",fullspec);
     265           0 :         strncpy(fullspec,temp,sizeof(fullspec));
     266           0 :     fullspec[sizeof(fullspec)-1] = '\0';
     267           0 :         free(temp);
     268             :     }
     269             : #if __Mac
     270             :     /* This seems a bit easier... Thanks to riggle */
     271             :     if ( strcmp(browser,"open")==0 ) {
     272             :         char *str = "DYLD_LIBRARY_PATH=\"\"; open ";
     273             :         if ( (temp=malloc(strlen(str) + strlen(fullspec) + 20))==NULL )
     274             :             return;
     275             :         sprintf( temp, "%s \"%s\" &", str, fullspec );
     276             :         system(temp);
     277             :         free(temp);
     278             :     } else {
     279             : #else
     280             :     {
     281             : #endif
     282           0 :         if ( (temp=malloc(strlen(browser) + strlen(fullspec) + 20))==NULL )
     283           0 :             return;
     284           0 :         sprintf( temp, strcmp(browser,"kfmclient openURL")==0 ? "%s \"%s\" &" : "\"%s\" \"%s\" &", browser, fullspec );
     285           0 :         system(temp);
     286           0 :         free(temp);
     287             :     }
     288             : }
     289             : #endif
     290             : 
     291           1 : static void UI_IError(const char *format,...) {
     292             :     va_list ap;
     293             :     char buffer[300];
     294           1 :     va_start(ap,format);
     295           1 :     vsnprintf(buffer,sizeof(buffer),format,ap);
     296           1 :     GDrawIError("%s",buffer);
     297           1 :     va_end(ap);
     298           1 : }
     299             : 
     300             : #define MAX_ERR_LINES   400
     301             : static struct errordata {
     302             :     char *errlines[MAX_ERR_LINES];
     303             :     GFont *font;
     304             :     int fh, as;
     305             :     GGadget *vsb;
     306             :     GWindow gw, v;
     307             :     int cnt, linecnt;
     308             :     int offtop;
     309             :     int showing;
     310             :     int start_l, start_c, end_l, end_c;
     311             :     int down;
     312             : } errdata;
     313             : 
     314           0 : static void ErrHide(void) {
     315           0 :     GDrawSetVisible(errdata.gw,false);
     316           0 :     errdata.showing = false;
     317           0 : }
     318             : 
     319           0 : static void ErrScroll(struct sbevent *sb) {
     320           0 :     int newpos = errdata.offtop;
     321             : 
     322           0 :     switch( sb->type ) {
     323             :       case et_sb_top:
     324           0 :         newpos = 0;
     325           0 :       break;
     326             :       case et_sb_uppage:
     327           0 :         newpos -= errdata.linecnt;
     328           0 :       break;
     329             :       case et_sb_up:
     330           0 :         --newpos;
     331           0 :       break;
     332             :       case et_sb_down:
     333           0 :         ++newpos;
     334           0 :       break;
     335             :       case et_sb_downpage:
     336           0 :         newpos += errdata.linecnt;
     337           0 :       break;
     338             :       case et_sb_bottom:
     339           0 :         newpos = errdata.cnt-errdata.linecnt;
     340           0 :       break;
     341             :       case et_sb_thumb:
     342             :       case et_sb_thumbrelease:
     343           0 :         newpos = sb->pos;
     344           0 :       break;
     345             :     }
     346           0 :     if ( newpos>errdata.cnt-errdata.linecnt )
     347           0 :         newpos = errdata.cnt-errdata.linecnt;
     348           0 :     if ( newpos<0 ) newpos =0;
     349           0 :     if ( newpos!=errdata.offtop ) {
     350           0 :         errdata.offtop = newpos;
     351           0 :         GScrollBarSetPos(errdata.vsb,errdata.offtop);
     352           0 :         GDrawRequestExpose(errdata.v,NULL,false);
     353             :     }
     354           0 : }
     355             : 
     356           0 : static int ErrChar(GEvent *e) {
     357           0 :     int newpos = errdata.offtop;
     358             : 
     359           0 :     switch( e->u.chr.keysym ) {
     360             :       case GK_Home:
     361           0 :         newpos = 0;
     362           0 :       break;
     363             :       case GK_End:
     364           0 :         newpos = errdata.cnt-errdata.linecnt;
     365           0 :       break;
     366             :       case GK_Page_Up: case GK_KP_Page_Up:
     367           0 :         newpos -= errdata.linecnt;
     368           0 :       break;
     369             :       case GK_Page_Down: case GK_KP_Page_Down:
     370           0 :         newpos += errdata.linecnt;
     371           0 :       break;
     372             :       case GK_Up: case GK_KP_Up:
     373           0 :         --newpos;
     374           0 :       break;
     375             :       case GK_Down: case GK_KP_Down:
     376           0 :         ++newpos;
     377           0 :       break;
     378             :     }
     379           0 :     if ( newpos>errdata.cnt-errdata.linecnt )
     380           0 :         newpos = errdata.cnt-errdata.linecnt;
     381           0 :     if ( newpos<0 ) newpos =0;
     382           0 :     if ( newpos!=errdata.offtop ) {
     383           0 :         errdata.offtop = newpos;
     384           0 :         GScrollBarSetPos(errdata.vsb,errdata.offtop);
     385           0 :         GDrawRequestExpose(errdata.v,NULL,false);
     386           0 : return( true );
     387             :     }
     388           0 : return( false );
     389             : }
     390             : 
     391           0 : static int warnings_e_h(GWindow gw, GEvent *event) {
     392             : 
     393           0 :     if (( event->type==et_mouseup || event->type==et_mousedown ) &&
     394           0 :             (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
     395           0 : return( GGadgetDispatchEvent(errdata.vsb,event));
     396             :     }
     397             : 
     398           0 :     switch ( event->type ) {
     399             :       case et_char:
     400           0 : return( ErrChar(event));
     401             :       break;
     402             :       case et_expose:
     403           0 :       break;
     404             :       case et_resize: {
     405             :           GRect size, sbsize;
     406           0 :           GDrawGetSize(gw,&size);
     407           0 :           GGadgetGetSize(errdata.vsb,&sbsize);
     408           0 :           GGadgetMove(errdata.vsb,size.width-sbsize.width,0);
     409           0 :           GGadgetResize(errdata.vsb,sbsize.width,size.height);
     410           0 :           GDrawResize(errdata.v,size.width-sbsize.width,size.height);
     411           0 :           errdata.linecnt = size.height/errdata.fh;
     412           0 :           GScrollBarSetBounds(errdata.vsb,0,errdata.cnt,errdata.linecnt);
     413           0 :           if ( errdata.offtop + errdata.linecnt > errdata.cnt ) {
     414           0 :               errdata.offtop = errdata.cnt-errdata.linecnt;
     415           0 :               if ( errdata.offtop < 0 ) errdata.offtop = 0;
     416           0 :               GScrollBarSetPos(errdata.vsb,errdata.offtop);
     417             :           }
     418           0 :           GDrawRequestExpose(errdata.v,NULL,false);
     419           0 :       } break;
     420             :       case et_controlevent:
     421           0 :         switch ( event->u.control.subtype ) {
     422             :           case et_scrollbarchange:
     423           0 :             ErrScroll(&event->u.control.u.sb);
     424           0 :           break;
     425             :         }
     426           0 :       break;
     427             :       case et_close:
     428           0 :         ErrHide();
     429           0 :       break;
     430             :       case et_create:
     431           0 :       break;
     432             :       case et_destroy:
     433           0 :       break;
     434             :     }
     435           0 : return( true );
     436             : }
     437             : 
     438           0 : static void noop(void *_ed) {
     439           0 : }
     440             : 
     441           0 : static void *genutf8data(void *_ed,int32 *len) {
     442             :     int cnt, l;
     443           0 :     int s_l = errdata.start_l, s_c = errdata.start_c, e_l = errdata.end_l, e_c = errdata.end_c;
     444             :     char *ret, *pt;
     445             : 
     446           0 :     if ( s_l>e_l ) {
     447           0 :         s_l = e_l; s_c = e_c; e_l = errdata.start_l; e_c = errdata.start_c;
     448             :     }
     449             : 
     450           0 :     if ( s_l==-1 ) {
     451           0 :         *len = 0;
     452           0 : return( copy(""));
     453             :     }
     454             : 
     455           0 :     l = s_l;
     456           0 :     if ( e_l == l ) {
     457           0 :         *len = e_c-s_c;
     458           0 : return( copyn( errdata.errlines[l]+s_c, e_c-s_c ));
     459             :     }
     460             : 
     461           0 :     cnt = strlen(errdata.errlines[l]+s_c)+1;
     462           0 :     for ( ++l; l<e_l; ++l )
     463           0 :         cnt += strlen(errdata.errlines[l])+1;
     464           0 :     cnt += e_c;
     465             : 
     466           0 :     ret = malloc(cnt+1);
     467           0 :     strcpy( ret, errdata.errlines[s_l]+s_c );
     468           0 :     pt = ret+strlen( ret );
     469           0 :     *pt++ = '\n';
     470           0 :     for ( l=s_l+1; l<e_l; ++l ) {
     471           0 :         strcpy(pt,errdata.errlines[l]);
     472           0 :         pt += strlen(pt);
     473           0 :         *pt++ = '\n';
     474             :     }
     475           0 :     strncpy(pt,errdata.errlines[l],e_c);
     476           0 :     *len = cnt;
     477           0 : return( ret );
     478             : }
     479             : 
     480           0 : static void MouseToPos(GEvent *event,int *_l, int *_c) {
     481           0 :     int l,c=0;
     482             : 
     483           0 :     GDrawSetFont(errdata.v,errdata.font);
     484           0 :     l = event->u.mouse.y/errdata.fh + errdata.offtop;
     485           0 :     if ( l>=errdata.cnt ) {
     486           0 :         l = errdata.cnt-1;
     487           0 :         if ( l>=0 )
     488           0 :             c = strlen(errdata.errlines[l]);
     489           0 :     } else if ( l>=0 ) {
     490           0 :         GDrawLayoutInit(errdata.v,errdata.errlines[l],-1,NULL);
     491           0 :         c = GDrawLayoutXYToIndex(errdata.v,event->u.mouse.x-3,4);
     492             :     }
     493           0 :     *_l = l;
     494           0 :     *_c = c;
     495           0 : }
     496             : 
     497           0 : static void WarnMenuCopy(GWindow gw,struct gmenuitem *mi,GEvent *e) {
     498           0 :     GDrawGrabSelection(gw,sn_clipboard);
     499           0 :     GDrawAddSelectionType(gw,sn_clipboard,"UTF8_STRING",&errdata,1,
     500             :             sizeof(char),
     501             :             genutf8data,noop);
     502           0 :     GDrawAddSelectionType(gw,sn_clipboard,"STRING",&errdata,1,
     503             :             sizeof(char),
     504             :             genutf8data,noop);
     505           0 : }
     506             : 
     507           0 : static void WarnMenuClear(GWindow gw,struct gmenuitem *mi,GEvent *e) {
     508             :     int i;
     509             : 
     510           0 :     for ( i=0; i<errdata.cnt; ++i ) {
     511           0 :         free(errdata.errlines[i]);
     512           0 :         errdata.errlines[i] = NULL;
     513             :     }
     514           0 :     errdata.cnt = 0;
     515           0 :     GDrawRequestExpose(gw,NULL,false);
     516           0 : }
     517             : 
     518             : #define MID_Copy        1
     519             : #define MID_Clear       2
     520             : 
     521             : GMenuItem warnpopupmenu[] = {
     522             :     { { (unichar_t *) N_("Cu_t"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 1, 0, 't' }, '\0', ksm_control, NULL, NULL, NULL, 0 },
     523             :     { { (unichar_t *) N_("_Copy"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'C' }, '\0', ksm_control, NULL, NULL, WarnMenuCopy, MID_Copy },
     524             :     { { (unichar_t *) N_("_Paste"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 1, 0, 0, 0, 0, 0, 1, 1, 0, 'P' }, '\0', ksm_control, NULL, NULL, NULL, 0 },
     525             :     { { (unichar_t *) N_("C_lear"), NULL, COLOR_DEFAULT, COLOR_DEFAULT, NULL, NULL, 0, 0, 0, 0, 0, 0, 1, 1, 0, 'l' }, 0, 0, NULL, NULL, WarnMenuClear, MID_Clear },
     526             :     GMENUITEM_EMPTY
     527             : };
     528             : 
     529           0 : static int warningsv_e_h(GWindow gw, GEvent *event) {
     530             :     int i;
     531             :     extern GBox _ggadget_Default_Box;
     532             : 
     533           0 :     if (( event->type==et_mouseup || event->type==et_mousedown ) &&
     534           0 :             (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
     535           0 : return( GGadgetDispatchEvent(errdata.vsb,event));
     536             :     }
     537             : 
     538           0 :     switch ( event->type ) {
     539             :       case et_expose:
     540             :           /*GDrawFillRect(gw,&event->u.expose.rect,GDrawGetDefaultBackground(NULL));*/
     541           0 :           GDrawSetFont(gw,errdata.font);
     542           0 :           for ( i=0; i<errdata.linecnt && i+errdata.offtop<errdata.cnt; ++i ) {
     543             :               int xs, xe;
     544           0 :               int s_l = errdata.start_l, s_c = errdata.start_c, e_l = errdata.end_l, e_c = errdata.end_c;
     545             :               GRect r;
     546           0 :               if ( s_l>e_l ) {
     547           0 :                   s_l = e_l; s_c = e_c; e_l = errdata.start_l; e_c = errdata.start_c;
     548             :               }
     549           0 :               GDrawLayoutInit(gw,errdata.errlines[i+errdata.offtop],-1,NULL);
     550           0 :               if ( i+errdata.offtop >= s_l && i+errdata.offtop <= e_l ) {
     551           0 :                   if ( i+errdata.offtop > s_l )
     552           0 :                       xs = 0;
     553             :                   else {
     554             :                       GRect pos;
     555           0 :                       GDrawLayoutIndexToPos(gw,s_c,&pos);
     556           0 :                       xs = pos.x+3;
     557             :                   }
     558           0 :                   if ( i+errdata.offtop < e_l )
     559           0 :                       xe = 3000;
     560             :                   else {
     561             :                       GRect pos;
     562           0 :                       GDrawLayoutIndexToPos(gw,s_c,&pos);
     563           0 :                       xe = pos.x+pos.width+3;
     564             :                   }
     565           0 :                   r.x = xs+3; r.width = xe-xs;
     566           0 :                   r.y = i*errdata.fh; r.height = errdata.fh;
     567           0 :                   GDrawFillRect(gw,&r,ACTIVE_BORDER);
     568             :               }
     569           0 :               GDrawLayoutDraw(gw,3,i*errdata.fh+errdata.as,MAIN_FOREGROUND);
     570             :           }
     571           0 :       break;
     572             :       case et_char:
     573           0 : return( ErrChar(event));
     574             :       break;
     575             :       case et_mousedown:
     576           0 :         if ( event->u.mouse.button==3 ) {
     577           0 :             warnpopupmenu[1].ti.disabled = errdata.start_l == -1;
     578           0 :             warnpopupmenu[3].ti.disabled = errdata.cnt == 0;
     579           0 :             GMenuCreatePopupMenu(gw,event, warnpopupmenu);
     580             :         } else {
     581           0 :             if ( errdata.down )
     582           0 : return( true );
     583           0 :             MouseToPos(event,&errdata.start_l,&errdata.start_c);
     584           0 :             errdata.down = true;
     585             :         }
     586             :       case et_mousemove:
     587             :       case et_mouseup:
     588           0 :         if ( !errdata.down )
     589           0 : return( true );
     590           0 :         MouseToPos(event,&errdata.end_l,&errdata.end_c);
     591           0 :         GDrawRequestExpose(gw,NULL,false);
     592           0 :         if ( event->type==et_mouseup ) {
     593           0 :             errdata.down = false;
     594           0 :             if ( errdata.start_l == errdata.end_l && errdata.start_c == errdata.end_c ) {
     595           0 :                 errdata.start_l = errdata.end_l = -1;
     596             :             } else {
     597           0 :                 GDrawGrabSelection(gw,sn_primary);
     598           0 :                 GDrawAddSelectionType(gw,sn_primary,"UTF8_STRING",&errdata,1,
     599             :                         sizeof(char),
     600             :                         genutf8data,noop);
     601           0 :                 GDrawAddSelectionType(gw,sn_primary,"STRING",&errdata,1,
     602             :                         sizeof(char),
     603             :                         genutf8data,noop);
     604             :             }
     605             :         }
     606           0 :       break;
     607             :       case et_selclear:
     608           0 :         errdata.start_l = errdata.end_l = -1;
     609           0 :         GDrawRequestExpose(gw,NULL,false);
     610           0 :       break;
     611             :       case et_timer:
     612           0 :       break;
     613             :       case et_focus:
     614           0 :       break;
     615             :     }
     616           0 : return( true );
     617             : }
     618             : 
     619           0 : static void CreateErrorWindow(void) {
     620             :     GWindowAttrs wattrs;
     621             :     FontRequest rq;
     622             :     GRect pos,size;
     623             :     int as, ds, ld;
     624             :     GWindow gw;
     625             :     GGadgetData gd;
     626             :     extern int _GScrollBar_Width;
     627             : 
     628           0 :     GDrawGetSize(GDrawGetRoot(NULL),&size);
     629             : 
     630           0 :     memset(&wattrs,0,sizeof(wattrs));
     631           0 :     wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_isdlg|wam_positioned;
     632           0 :     wattrs.event_masks = ~(1<<et_charup);
     633           0 :     wattrs.is_dlg = true;
     634           0 :     wattrs.cursor = ct_pointer;
     635           0 :     wattrs.positioned = true;
     636           0 :     wattrs.utf8_window_title = _("Warnings");
     637           0 :     pos.width = GDrawPointsToPixels(NULL,GGadgetScale(400));
     638           0 :     pos.height = GDrawPointsToPixels(NULL,GGadgetScale(100));
     639           0 :     pos.x = size.width - pos.width - 10;
     640           0 :     pos.y = size.height - pos.height - 30;
     641           0 :     errdata.gw = gw = GDrawCreateTopWindow(NULL,&pos,warnings_e_h,&errdata,&wattrs);
     642             : 
     643           0 :     memset(&rq,0,sizeof(rq));
     644           0 :     rq.utf8_family_name = SANS_UI_FAMILIES;
     645           0 :     rq.point_size = 10;
     646           0 :     rq.weight = 400;
     647           0 :     errdata.font = GDrawInstanciateFont(NULL,&rq);
     648           0 :     errdata.font = GResourceFindFont("Warnings.Font",errdata.font);
     649           0 :     GDrawWindowFontMetrics(errdata.gw,errdata.font,&as,&ds,&ld);
     650           0 :     errdata.as = as;
     651           0 :     errdata.fh = as+ds;
     652             : 
     653           0 :     memset(&gd,0,sizeof(gd));
     654           0 :     gd.pos.y = 0; gd.pos.height = pos.height;
     655           0 :     gd.pos.width = GDrawPointsToPixels(gw,_GScrollBar_Width);
     656           0 :     gd.pos.x = pos.width-gd.pos.width;
     657           0 :     gd.flags = gg_visible|gg_enabled|gg_pos_in_pixels|gg_sb_vert;
     658           0 :     errdata.vsb = GScrollBarCreate(gw,&gd,&errdata);
     659             : 
     660           0 :     pos.width -= gd.pos.width;
     661           0 :     pos.x = pos.y = 0;
     662           0 :     wattrs.mask = wam_events|wam_cursor;
     663           0 :     errdata.v = GWidgetCreateSubWindow(gw,&pos,warningsv_e_h,&errdata,&wattrs);
     664           0 :     GDrawSetVisible(errdata.v,true);
     665             : 
     666           0 :     errdata.linecnt = pos.height/errdata.fh;
     667           0 :     errdata.start_l = errdata.end_l = -1;
     668           0 : }
     669             : 
     670           0 : static void AppendToErrorWindow(char *buffer) {
     671             :     int i,linecnt;
     672             :     char *pt,*end;
     673             : 
     674           0 :     if ( buffer[strlen(buffer)-1]=='\n' ) buffer[strlen(buffer)-1] = '\0';
     675             : 
     676           0 :     for ( linecnt=1, pt=buffer; (pt=strchr(pt,'\n'))!=NULL; ++linecnt )
     677           0 :         ++pt;
     678           0 :     if ( errdata.cnt + linecnt > MAX_ERR_LINES ) {
     679           0 :         int off = errdata.cnt + linecnt - MAX_ERR_LINES;
     680           0 :         for ( i=0; i<off; ++i )
     681           0 :             free(errdata.errlines[i]);
     682           0 :         for ( /*i=off*/; i<errdata.cnt; ++i )
     683           0 :             errdata.errlines[i-off] = errdata.errlines[i];
     684           0 :         for ( ; i<MAX_ERR_LINES+off ; ++i )
     685           0 :             errdata.errlines[i-off] = NULL;
     686           0 :         errdata.cnt -= off;
     687           0 :         if (( errdata.start_l -= off)< 0 ) errdata.start_l = errdata.start_c = 0;
     688           0 :         if (( errdata.end_l -= off)< 0 ) errdata.end_l = errdata.start_l = -1;
     689             :     }
     690           0 :     for ( i=errdata.cnt, pt=buffer; i<MAX_ERR_LINES; ++i ) {
     691           0 :         end = strchr(pt,'\n');
     692           0 :         if ( end==NULL ) end = pt+strlen(pt);
     693           0 :         errdata.errlines[i] = copyn(pt,end-pt);
     694           0 :         pt = end;
     695           0 :         if ( *pt=='\0' ) {
     696           0 :             ++i;
     697           0 :     break;
     698             :         }
     699           0 :         ++pt;
     700             :     }
     701           0 :     errdata.cnt = i;
     702             : 
     703           0 :     errdata.offtop = errdata.cnt - errdata.linecnt;
     704           0 :     if ( errdata.offtop<0 ) errdata.offtop = 0;
     705           0 :     GScrollBarSetBounds(errdata.vsb,0,errdata.cnt,errdata.linecnt);
     706           0 :     GScrollBarSetPos(errdata.vsb,errdata.offtop);
     707           0 : }
     708             : 
     709           0 : int ErrorWindowExists(void) {
     710           0 : return( errdata.gw!=NULL );
     711             : }
     712             : 
     713           0 : void ShowErrorWindow(void) {
     714           0 :     if ( errdata.gw==NULL )
     715           0 : return;
     716           0 :     GDrawSetVisible(errdata.gw,true);
     717           0 :     GDrawRaise(errdata.gw);
     718           0 :     if ( errdata.showing )
     719           0 :         GDrawRequestExpose(errdata.v,NULL,false);
     720           0 :     errdata.showing = true;
     721             : }
     722             : 
     723         201 : static void _LogError(const char *format,va_list ap) {
     724             :     char buffer[2500], nbuffer[2600], *str, *pt, *npt;
     725         201 :     vsnprintf(buffer,sizeof(buffer),format,ap);
     726       17831 :     for ( pt=buffer, npt=nbuffer; *pt!='\0' && npt<nbuffer+sizeof(nbuffer)-2; ) {
     727       17429 :         *npt++ = *pt++;
     728       17429 :         if ( pt[-1]=='\n' && *pt!='\0' ) {
     729             :             /* Force an indent of at least two spaces on secondary lines of a warning */
     730          50 :             if ( npt<nbuffer+sizeof(nbuffer)-2 ) {
     731          50 :                 *npt++ = ' ';
     732          50 :                 if ( *pt==' ' ) ++pt;
     733             :             }
     734          50 :             if ( npt<nbuffer+sizeof(nbuffer)-2 ) {
     735          50 :                 *npt++ = ' ';
     736          50 :                 if ( *pt==' ' ) ++pt;
     737             :             }
     738             :         }
     739             :     }
     740         201 :     *npt='\0';
     741             : 
     742         201 :     if ( no_windowing_ui || screen_display==NULL ) {
     743         201 :         str = utf82def_copy(nbuffer);
     744         201 :         fprintf(stderr,"%s",str);
     745         201 :         if ( str[strlen(str)-1]!='\n' )
     746         154 :             putc('\n',stderr);
     747         201 :         free(str);
     748             :     } else {
     749           0 :         if ( !ErrorWindowExists())
     750           0 :             CreateErrorWindow();
     751           0 :         AppendToErrorWindow(nbuffer);
     752           0 :         ShowErrorWindow();
     753             :     }
     754         201 : }
     755             : 
     756         201 : static void UI_LogError(const char *format,...) {
     757             :     va_list ap;
     758             : 
     759         201 :     va_start(ap,format);
     760         201 :     _LogError(format,ap);
     761         201 :     va_end(ap);
     762         201 : }
     763             : 
     764           0 : static void UI_post_notice(const char *title,const char *statement,...) {
     765             :     va_list ap;
     766           0 :     va_start(ap,statement);
     767           0 :     if ( no_windowing_ui ) {
     768           0 :         _LogError(statement,ap);
     769             :     } else {
     770           0 :         if ( GWidgetPostNoticeActive8(title))
     771           0 :             _LogError(statement,ap);
     772             :         else
     773           0 :             _GWidgetPostNotice8(title,statement,ap,40);
     774             :     }
     775           0 :     va_end(ap);
     776           0 : }
     777             : 
     778           0 : static char *UI_open_file(const char *title, const char *defaultfile,
     779             :         const char *initial_filter) {
     780           0 : return( gwwv_open_filename(title,defaultfile,initial_filter,NULL) );
     781             : }
     782             : 
     783           0 : static char *UI_saveas_file(const char *title, const char *defaultfile,
     784             :         const char *initial_filter) {
     785           0 : return( gwwv_save_filename(title,defaultfile,initial_filter) );
     786             : }
     787             : 
     788           0 : static void tinysleep(int microsecs) {
     789             : #if !defined(__MINGW32__)
     790             :     fd_set none;
     791             :     struct timeval timeout;
     792             : 
     793           0 :     FD_ZERO(&none);
     794           0 :     memset(&timeout,0,sizeof(timeout));
     795           0 :     timeout.tv_usec = microsecs;
     796             : 
     797           0 :     select(1,&none,&none,&none,&timeout);
     798             : #endif
     799           0 : }
     800             : 
     801           0 : static void allow_events(void) {
     802           0 :     GDrawSync(NULL);
     803           0 :     tinysleep(100);
     804           0 :     GDrawProcessPendingEvents(NULL);
     805           0 : }
     806             : 
     807             : 
     808             : struct ui_interface gdraw_ui_interface = {
     809             :     UI_IError,
     810             :     gwwv_post_error,
     811             :     UI_LogError,
     812             :     UI_post_notice,
     813             :     gwwv_ask_centered,
     814             :     gwwv_choose,
     815             :     gwwv_choose_multiple,
     816             :     gwwv_ask_string,
     817             :     gwwv_ask_password,
     818             :     UI_open_file,
     819             :     UI_saveas_file,
     820             :     gwwv_progress_start_indicator,
     821             :     gwwv_progress_end_indicator,
     822             :     gwwv_progress_show,
     823             :     gwwv_progress_enable_stop,
     824             :     gwwv_progress_next,
     825             :     gwwv_progress_next_stage,
     826             :     gwwv_progress_increment,
     827             :     gwwv_progress_change_line1,
     828             :     gwwv_progress_change_line2,
     829             :     gwwv_progress_pause_timer,
     830             :     gwwv_progress_resume_timer,
     831             :     gwwv_progress_change_stages,
     832             :     gwwv_progress_change_total,
     833             :     gwwv_progress_reset,
     834             : 
     835             :     allow_events,
     836             : 
     837             :     UI_TTFNameIds,
     838             :     UI_MSLangString,
     839             :     (int (*)(void)) Ps_StrokeFlagsDlg
     840             : };
     841             : 

Generated by: LCOV version 1.10