LCOV - code coverage report
Current view: top level - gdraw - gprogress.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 48 290 16.6 %
Date: 2017-08-04 Functions: 13 27 48.1 %

          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             : #include <gprogress.h>
      29             : #include <ggadget.h>
      30             : #include <gwidget.h>
      31             : #include <gresource.h>
      32             : #include <ustring.h>
      33             : #include <memory.h>
      34             : #include <sys/time.h>
      35             : #include "ggadgetP.h"         /* For the font family names */
      36             : 
      37             : typedef struct gprogress {
      38             :     struct timeval start_time;  /* Don't pop up unless we're after this */
      39             :     struct timeval pause_time;
      40             :     unichar_t *line1;
      41             :     unichar_t *line2;
      42             :     int sofar;
      43             :     int tot;
      44             :     int16 stage, stages;
      45             :     int16 width;
      46             :     int16 l1width, l2width;
      47             :     int16 l1y, l2y, boxy;
      48             :     int16 last_amount;
      49             :     unsigned int aborted: 1;
      50             :     unsigned int visible: 1;
      51             :     unsigned int dying: 1;
      52             :     unsigned int paused: 1;
      53             :     unsigned int sawmap: 1;
      54             :     GWindow gw;
      55             :     GFont *font;
      56             :     struct gprogress *prev;
      57             : } GProgress;
      58             : 
      59             : static Color progress_background, progress_foreground;
      60             : static Color progress_fillcol = 0xc0c0ff;
      61             : static GFont *progress_font = NULL;
      62             : static int progress_init = false;
      63             : 
      64             : static GProgress *current;
      65             : 
      66           0 : static void GProgressDisplay(void) {
      67           0 :     GDrawSetVisible(current->gw,true);
      68           0 :     current->visible = true;
      69           0 :     if ( current->prev!=NULL && current->prev->visible ) {
      70           0 :         GDrawSetVisible(current->prev->gw,false);
      71           0 :         current->prev->visible = false;
      72             :     }
      73           0 : }
      74             : 
      75           0 : static void GProgressTimeCheck() {
      76             :     struct timeval tv;
      77             : 
      78           0 :     if ( current==NULL || current->visible || current->dying || current->paused )
      79           0 : return;
      80           0 :     gettimeofday(&tv,NULL);
      81           0 :     if ( tv.tv_sec>current->start_time.tv_sec ||
      82           0 :             (tv.tv_sec==current->start_time.tv_sec && tv.tv_usec>current->start_time.tv_usec )) {
      83           0 :         if ( current->tot>0 &&
      84           0 :                 current->sofar+current->stage*current->tot>(9*current->stages*current->tot)/10 )
      85           0 : return;         /* If it's almost done, no point in making it visible */
      86           0 :         GProgressDisplay();
      87             :     }
      88             : }
      89             : 
      90           0 : static void GProgressDraw(GProgress *p,GWindow pixmap,GRect *rect) {
      91             :     GRect r, old;
      92             :     int width, amount;
      93             : 
      94           0 :     GDrawPushClip(pixmap,rect,&old);
      95           0 :     GDrawSetFont(pixmap,p->font);
      96           0 :     if ( p->line1!=NULL )
      97           0 :         GDrawDrawText(pixmap, (p->width-p->l1width)/2, p->l1y, p->line1, -1,
      98             :                 progress_foreground );
      99           0 :     if ( p->line2!=NULL )
     100           0 :         GDrawDrawText(pixmap, (p->width-p->l2width)/2, p->l2y, p->line2, -1,
     101             :                 progress_foreground );
     102             : 
     103           0 :     r.x = GDrawPointsToPixels(pixmap,10);
     104           0 :     r.y = p->boxy;
     105           0 :     r.height = r.x;
     106           0 :     width = p->width-2*r.x;
     107             :     
     108           0 :     if ( p->tot==0 )
     109           0 :         amount = 0;
     110             :     else
     111           0 :         amount = width * (p->stage*p->tot + p->sofar)/(p->stages*p->tot);
     112           0 :     if ( amount>0 ) {
     113           0 :         r.width = amount;
     114           0 :         GDrawFillRect(pixmap,&r,progress_fillcol);
     115           0 :     } else if ( p->tot==0 ) {
     116           0 :         r.width = width;
     117           0 :         GDrawSetStippled(pixmap,1,0,0);
     118           0 :         GDrawFillRect(pixmap,&r,progress_fillcol);
     119           0 :         GDrawSetStippled(pixmap,0,0,0);
     120             :     }
     121           0 :     r.width = width;
     122           0 :     GDrawDrawRect(pixmap,&r,progress_foreground);
     123           0 :     GDrawPopClip(pixmap,&old);
     124           0 : }
     125             : 
     126           0 : static int GProgressProcess(GProgress *p) {
     127             :     int width, amount;
     128             :     int tenpt;
     129             : 
     130           0 :     if ( !p->visible )
     131           0 :         GProgressTimeCheck();
     132             : 
     133           0 :     tenpt = GDrawPointsToPixels(p->gw,10);
     134           0 :     width = p->width-2*tenpt;
     135           0 :     if ( p->tot==0 )
     136           0 :         amount = 0;
     137             :     else
     138           0 :         amount = width * (p->stage*p->tot + p->sofar)/(p->stages*p->tot);
     139           0 :     if ( amount!=p->last_amount ) {
     140           0 :         if ( amount<p->last_amount || p->last_amount==0 )
     141           0 :             GDrawRequestExpose(p->gw,NULL,false);
     142             :         else {
     143             :             GRect r;
     144           0 :             r.height = tenpt-1;
     145           0 :             r.width = amount - p->last_amount;
     146           0 :             r.x = tenpt + p->last_amount;
     147           0 :             r.y = p->boxy+1;
     148           0 :             GDrawFillRect(p->gw,&r,progress_fillcol);
     149             :         }
     150           0 :         p->last_amount = amount;
     151             :     }
     152           0 :     GDrawProcessPendingEvents(NULL);
     153           0 : return( !p->aborted );
     154             : }
     155             : 
     156           0 : static int progress_eh(GWindow gw, GEvent *event) {
     157           0 :     GProgress *p = GDrawGetUserData(gw);
     158             : 
     159           0 :     switch ( event->type ) {
     160             :       case et_destroy:
     161           0 :         free(p->line1);
     162           0 :         free(p->line2);
     163           0 :         free(p);
     164           0 :       break;
     165             :       case et_close:
     166           0 :         p->aborted = true;
     167           0 :         GDrawSetVisible(gw,false);
     168           0 :       break;
     169             :       case et_expose:
     170           0 :         GProgressDraw(p,gw,&event->u.expose.rect);
     171           0 :       break;
     172             :       case et_controlevent:
     173           0 :         if ( event->u.control.subtype == et_buttonactivate )
     174           0 :             p->aborted = true;
     175           0 :       break;
     176             :       case et_char:
     177           0 :         if ( (event->u.chr.state&ksm_control) && event->u.chr.chars[0]=='.' )
     178           0 :             p->aborted = true;
     179           0 :       break;
     180             :       case et_map:
     181           0 :         p->sawmap = true;
     182           0 :       break;
     183             :     }
     184           0 : return( true );
     185             : }
     186             : 
     187             : /* ************************************************************************** */
     188             : static struct resed progress_re[] = {
     189             :     {N_("Color|Foreground"), "Foreground", rt_color, &progress_foreground, N_("Text color for progress windows"), NULL, { 0 }, 0, 0 },
     190             :     {N_("Color|FillColor"), "FillColor", rt_color, &progress_fillcol, N_("Color used to draw the progress bar"), NULL, { 0 }, 0, 0 },
     191             :     {N_("Color|Background"), "Background", rt_color, &progress_background, N_("Background color for progress windows"), NULL, { 0 }, 0, 0 },
     192             :     RESED_EMPTY
     193             : };
     194             : static GResInfo progress_ri = {
     195             :     NULL, NULL, NULL,NULL,
     196             :     NULL,       /* No box */
     197             :     &progress_font,
     198             :     NULL,
     199             :     progress_re,
     200             :     N_("Progress"),
     201             :     N_("Progress Bars"),
     202             :     "GProgress",
     203             :     "Gdraw",
     204             :     false,
     205             :     0,
     206             :     NULL,
     207             :     GBOX_EMPTY,
     208             :     NULL,
     209             :     NULL,
     210             :     NULL
     211             : };
     212             : 
     213           0 : static void GProgressResInit(void) {
     214           0 :     if ( !progress_init ) {
     215           0 :         progress_foreground = GResourceFindColor("GProgress.Foreground",
     216             :                     GDrawGetDefaultForeground(NULL));
     217           0 :         progress_background = GResourceFindColor("GProgress.Background",
     218             :                     GDrawGetDefaultBackground(NULL));
     219           0 :         progress_fillcol = GResourceFindColor("GProgress.FillColor",
     220             :                     progress_fillcol);
     221           0 :         progress_font = GResourceFindFont("GProgress.Font",NULL);
     222           0 :         progress_init = true;
     223             :     }
     224           0 : }
     225             : 
     226         119 : void GProgressStartIndicator(
     227             :     int delay,                  /* in tenths of seconds */
     228             :     const unichar_t *win_title, /* for the window decoration */
     229             :     const unichar_t *line1,     /* First line of description */
     230             :     const unichar_t *line2,     /* Second line */
     231             :     int tot,                    /* Number of sub-entities in the operation */
     232             :     int stages                  /* Number of stages, each processing tot sub-entities */
     233             : ) {
     234             :     GProgress *new;
     235             :     FontRequest rq;
     236             :     GWindowAttrs wattrs;
     237             :     GWindow root;
     238             :     GGadgetData gd;
     239             :     int ld, as, ds;
     240             :     GRect pos;
     241             :     struct timeval tv;
     242             :     GTextInfo label;
     243             : 
     244         119 :     if ( screen_display==NULL )
     245         238 : return;
     246             : 
     247           0 :     if ( !progress_init )
     248           0 :         GProgressResInit();
     249           0 :     new = calloc(1,sizeof(GProgress));
     250           0 :     new->line1 = u_copy(line1);
     251           0 :     new->line2 = u_copy(line2);
     252           0 :     new->tot = tot;
     253           0 :     new->stages = stages;
     254           0 :     new->prev = current;
     255             : 
     256           0 :     root = GDrawGetRoot(NULL);
     257           0 :     if ( progress_font == NULL ) {
     258           0 :         memset(&rq,'\0',sizeof(rq));
     259           0 :         rq.utf8_family_name = MONO_UI_FAMILIES;
     260           0 :         rq.point_size = 12;
     261           0 :         rq.weight = 400;
     262           0 :         progress_font = GDrawAttachFont(root,&rq);
     263             :     } else {
     264           0 :         GDrawSetFont(root, progress_font);
     265             :     }
     266           0 :     GDrawWindowFontMetrics(root,new->font = progress_font,&as,&ds,&ld);
     267             : 
     268           0 :     if ( new->line1!=NULL )
     269           0 :         new->l1width = GDrawGetTextWidth(root,new->line1,-1);
     270           0 :     if ( new->line2!=NULL )
     271           0 :         new->l2width = GDrawGetTextWidth(root,new->line2,-1);
     272           0 :     new->l1y = GDrawPointsToPixels(root,5) + as;
     273           0 :     new->l2y = new->l1y + as+ds;
     274           0 :     new->boxy = new->l2y + as+ds;
     275           0 :     pos.width = (new->l1width>new->l2width)?new->l1width:new->l2width;
     276           0 :     if ( pos.width<GDrawPointsToPixels(root,100) )
     277           0 :         pos.width = GDrawPointsToPixels(root,100);
     278           0 :     pos.width += 2 * GDrawPointsToPixels(root,10);
     279           0 :     pos.height = new->boxy + GDrawPointsToPixels(root,44);
     280           0 :     new->width = pos.width;
     281             : 
     282           0 :     memset(&wattrs,0,sizeof(wattrs));
     283           0 :     wattrs.mask = wam_events|wam_cursor|(win_title!=NULL?wam_wtitle:0)|
     284             :             wam_centered|wam_restrict|wam_redirect|wam_isdlg|wam_backcol;
     285           0 :     wattrs.event_masks = ~(1<<et_charup);
     286           0 :     wattrs.cursor = ct_watch;
     287           0 :     wattrs.window_title = u_copy(win_title);
     288           0 :     wattrs.centered = true;
     289           0 :     wattrs.restrict_input_to_me = true;
     290           0 :     wattrs.redirect_chars_to_me = true;
     291           0 :     wattrs.is_dlg = true;
     292           0 :     wattrs.redirect_from = NULL;
     293           0 :     wattrs.background_color = progress_background;
     294           0 :     pos.x = pos.y = 0;
     295           0 :     new->gw = GDrawCreateTopWindow(NULL,&pos,progress_eh,new,&wattrs);
     296           0 :     free((void *) wattrs.window_title);
     297             : 
     298           0 :     memset(&gd,'\0',sizeof(gd)); memset(&label,'\0',sizeof(label));
     299           0 :     gd.pos.width = GDrawPointsToPixels(new->gw,50);
     300           0 :     gd.pos.x = pos.width-gd.pos.width-10;
     301           0 :     gd.pos.y = pos.height-GDrawPointsToPixels(new->gw,29);
     302           0 :     gd.flags = gg_visible | gg_enabled | gg_pos_in_pixels | gg_pos_use0;
     303           0 :     gd.mnemonic = 'S';
     304           0 :     label.text = (unichar_t *) _("_Stop");
     305           0 :     label.text_is_1byte = true;
     306           0 :     label.text_in_resource = true;
     307           0 :     gd.label = &label;
     308           0 :     GButtonCreate( new->gw, &gd, NULL);
     309             : 
     310             :     /* If there's another progress indicator up, it will not move and ours */
     311             :     /*  won't be visible if we have a delay, so force delay to 0 here */
     312           0 :     if ( current!=NULL ) delay = 0;
     313           0 :     gettimeofday(&tv,NULL);
     314           0 :     new->start_time = tv;
     315           0 :     new->start_time.tv_usec += (delay%10)*100000;
     316           0 :     new->start_time.tv_sec += delay/10;
     317           0 :     if ( new->start_time.tv_usec >= 1000000 ) {
     318           0 :         ++new->start_time.tv_sec;
     319           0 :         new->start_time.tv_usec -= 1000000;
     320             :     }
     321             : 
     322           0 :     current = new;
     323           0 :     GProgressTimeCheck();
     324             : }
     325             : 
     326           0 : void GProgressStartIndicatorR( int delay, int win_titler, int line1r, int line2r,
     327             :     int tot, int stages ) {
     328           0 :     GProgressStartIndicator(delay,
     329             :         GStringGetResource(win_titler,NULL),
     330             :         GStringGetResource(line1r,NULL),
     331             :         line2r==0?NULL:GStringGetResource(line2r,NULL),
     332             :         tot,stages);
     333           0 : }
     334             : 
     335         119 : void GProgressEndIndicator(void) {
     336         119 :     GProgress *old=current;
     337             : 
     338         119 :     if ( old==NULL )
     339         238 : return;
     340           0 :     current = old->prev;
     341             :     
     342           0 :     old->dying = true;
     343             :     /* the X server sometimes crashes if we: */
     344             :             /* Create a window */
     345             :             /* map it */
     346             :             /* but destroy it before the server can send us the map notify event */
     347             :             /* next three lines seem to deal with it */
     348             :     /* unmapping the window also causes a crash */
     349           0 :     if ( old->visible ) while ( !old->sawmap ) {
     350           0 :         GDrawSync(NULL);
     351           0 :         GDrawProcessPendingEvents(NULL);
     352             :     }
     353           0 :     GDrawDestroyWindow(old->gw);
     354           0 :     GDrawSync(NULL);
     355           0 :     GDrawProcessPendingEvents(NULL);
     356             : }
     357             : 
     358          69 : void GProgressChangeLine1(const unichar_t *line1) {
     359          69 :     if ( current==NULL )
     360         138 : return;
     361           0 :     free( current->line1 );
     362           0 :     current->line1 = u_copy(line1);
     363           0 :     if ( current->line1!=NULL ) {
     364           0 :         GDrawSetFont(current->gw,current->font);
     365           0 :         current->l1width = GDrawGetTextWidth(current->gw,current->line1,-1);
     366             :     }
     367           0 :     if ( current->visible )
     368           0 :         GDrawRequestExpose(current->gw,NULL,false);
     369             : }
     370             : 
     371           0 : void GProgressChangeLine1R(int line1r) {
     372           0 :     GProgressChangeLine1(GStringGetResource(line1r,NULL));
     373           0 : }
     374             : 
     375         120 : void GProgressChangeLine2(const unichar_t *line2) {
     376         120 :     if ( current==NULL )
     377         240 : return;
     378           0 :     free( current->line2 );
     379           0 :     current->line2 = u_copy(line2);
     380           0 :     if ( current->line2!=NULL ) {
     381           0 :         GDrawSetFont(current->gw,current->font);
     382           0 :         current->l2width = GDrawGetTextWidth(current->gw,current->line2,-1);
     383             :     }
     384           0 :     if ( current->visible )
     385           0 :         GDrawRequestExpose(current->gw,NULL,false);
     386             : }
     387             : 
     388           0 : void GProgressChangeLine2R(int line2r) {
     389           0 :     GProgressChangeLine2(GStringGetResource(line2r,NULL));
     390           0 : }
     391             : 
     392          72 : void GProgressChangeTotal(int tot) {
     393          72 :     if ( current==NULL )
     394         144 : return;
     395           0 :     current->tot = tot;
     396             : }
     397             : 
     398         113 : void GProgressChangeStages(int stages) {
     399         113 :     if ( current==NULL )
     400         226 : return;
     401           0 :     if ( stages<=0 )
     402           0 :         stages = 1;
     403           0 :     current->stages = stages;
     404           0 :     if ( current->stage>=stages )
     405           0 :         current->stage = stages-1;
     406             : }
     407             : 
     408          67 : void GProgressEnableStop(int enabled) {
     409          67 :     if ( current==NULL )
     410         134 : return;
     411           0 :     GGadgetSetEnabled(GWidgetGetControl(current->gw,0),enabled);
     412             : }
     413             : 
     414         216 : int GProgressNextStage(void) {
     415             : 
     416         216 :     if ( current==NULL )
     417         216 : return(true);
     418           0 :     ++current->stage;
     419           0 :     current->sofar = 0;
     420           0 :     if ( current->stage>=current->stages )
     421           0 :         current->stage = current->stages-1;
     422           0 : return( GProgressProcess(current));
     423             : }
     424             : 
     425      161602 : int GProgressNext(void) {
     426             : 
     427      161602 :     if ( current==NULL )
     428      161602 : return(true);
     429           0 :     ++current->sofar;
     430           0 :     if ( current->sofar>=current->tot )
     431           0 :         current->sofar = current->tot-1;
     432           0 : return( GProgressProcess(current));
     433             : }
     434             : 
     435          10 : int GProgressIncrementBy(int cnt) {
     436             : 
     437          10 :     if ( current==NULL )
     438          10 : return(true);
     439           0 :     current->sofar += cnt;
     440           0 :     if ( current->sofar>=current->tot )
     441           0 :         current->sofar = current->tot-1;
     442           0 : return( GProgressProcess(current));
     443             : }
     444             : 
     445           0 : int GProgressReset(void) {
     446             : 
     447           0 :     if ( current==NULL )
     448           0 : return(true);
     449           0 :     current->sofar = 0;
     450           0 : return( GProgressProcess(current));
     451             : }
     452             : 
     453           0 : void GProgressPauseTimer(void) {
     454           0 :     if ( current==NULL || current->visible || current->dying || current->paused )
     455           0 : return;
     456           0 :     gettimeofday(&current->pause_time,NULL);
     457           0 :     current->paused = true;
     458             : }
     459             : 
     460           0 : void GProgressResumeTimer(void) {
     461             :     struct timeval tv, res;
     462             : 
     463           0 :     if ( current==NULL || current->visible || current->dying || !current->paused )
     464           0 : return;
     465           0 :     current->paused = false;
     466           0 :     gettimeofday(&tv,NULL);
     467           0 :     res.tv_sec = tv.tv_sec - current->pause_time.tv_sec;
     468           0 :     if ( (res.tv_usec = tv.tv_usec - current->pause_time.tv_usec)<0 ) {
     469           0 :         --res.tv_sec;
     470           0 :         res.tv_usec += 1000000;
     471             :     }
     472           0 :     current->start_time.tv_sec += res.tv_sec;
     473           0 :     if ( (current->start_time.tv_usec += res.tv_usec)>= 1000000 ) {
     474           0 :         ++current->start_time.tv_sec;
     475           0 :         current->start_time.tv_usec -= 1000000;
     476             :     }
     477             : }
     478             : 
     479           0 : void GProgressShow(void) {
     480             : 
     481           0 :     if ( current==NULL || current->visible || current->dying )
     482           0 : return;
     483             : 
     484           0 :     GProgressDisplay();
     485           0 :     GDrawSync(NULL);
     486           0 :     GDrawProcessPendingEvents(NULL);
     487           0 :     GDrawSync(NULL);
     488           0 :     GDrawProcessPendingEvents(NULL);
     489             : }
     490             : 
     491         119 : void GProgressStartIndicator8(int delay, const char *title, const char *line1,
     492             :         const char *line2, int tot, int stages) {
     493         119 :     unichar_t *tit = utf82u_copy(title),
     494         119 :                 *l1 = utf82u_copy(line1),
     495         119 :                 *l2 = utf82u_copy(line2);
     496         119 :     GProgressStartIndicator(delay,
     497             :         tit,l1,l2,
     498             :         tot,stages);
     499         119 :     free(l1); free(l2); free(tit);
     500         119 : }
     501             : 
     502          69 : void GProgressChangeLine1_8(const char *line1) {
     503          69 :     unichar_t *l1 = utf82u_copy(line1);
     504          69 :     GProgressChangeLine1(l1);
     505          69 :     free(l1);
     506          69 : }
     507             : 
     508         120 : void GProgressChangeLine2_8(const char *line2) {
     509         120 :     unichar_t *l2 = utf82u_copy(line2);
     510         120 :     GProgressChangeLine2(l2);
     511         120 :     free(l2);
     512         120 : }
     513             : 
     514           0 : GResInfo *_GProgressRIHead(void) {
     515             : 
     516           0 :     if ( !progress_init )
     517           0 :         GProgressResInit();
     518           0 : return( &progress_ri );
     519             : }

Generated by: LCOV version 1.10