Manual pages: mc • mcdiff • mcedit • mcview

root/lib/widget/gauge.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. gauge_report_to_terminal
  2. gauge_callback
  3. gauge_new
  4. gauge_set_value
  5. gauge_show

   1 /*
   2    Widgets for the Midnight Commander
   3 
   4    Copyright (C) 1994-2026
   5    Free Software Foundation, Inc.
   6 
   7    Authors:
   8    Radek Doulik, 1994, 1995
   9    Miguel de Icaza, 1994, 1995
  10    Jakub Jelinek, 1995
  11    Andrej Borsenkow, 1996
  12    Norbert Warmuth, 1997
  13    Andrew Borodin <aborodin@vmail.ru>, 2009-2022
  14 
  15    This file is part of the Midnight Commander.
  16 
  17    The Midnight Commander is free software: you can redistribute it
  18    and/or modify it under the terms of the GNU General Public License as
  19    published by the Free Software Foundation, either version 3 of the License,
  20    or (at your option) any later version.
  21 
  22    The Midnight Commander is distributed in the hope that it will be useful,
  23    but WITHOUT ANY WARRANTY; without even the implied warranty of
  24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25    GNU General Public License for more details.
  26 
  27    You should have received a copy of the GNU General Public License
  28    along with this program.  If not, see <https://www.gnu.org/licenses/>.
  29  */
  30 
  31 /** \file gauge.c
  32  *  \brief Source: WGauge widget (progress indicator)
  33  */
  34 
  35 #include <config.h>
  36 
  37 #include <stdio.h>
  38 #include <stdlib.h>
  39 #include <string.h>
  40 
  41 #include "lib/global.h"
  42 
  43 #include "lib/tty/tty.h"
  44 #include "lib/tty/color.h"
  45 #include "lib/skin.h"
  46 #include "lib/widget.h"
  47 
  48 /*** global variables ****************************************************************************/
  49 
  50 /*** file scope macro definitions ****************************************************************/
  51 
  52 /*** file scope type declarations ****************************************************************/
  53 
  54 /*** forward declarations (file scope functions) *************************************************/
  55 
  56 /*** file scope variables ************************************************************************/
  57 
  58 /* --------------------------------------------------------------------------------------------- */
  59 /*** file scope functions ************************************************************************/
  60 /* --------------------------------------------------------------------------------------------- */
  61 /**
  62  * Show the progress in the terminal's tab, title bar or taskbar, using the ConEmu
  63  * "OSC 9 ; 4" sequence supported by Windows Terminal, GNOME Terminal (VTE), iTerm2 and others.
  64  *
  65  * @param g          gauge
  66  * @param percentage progress to report, -1 to remove the progress indicator
  67  */
  68 
  69 static void
  70 gauge_report_to_terminal (WGauge *g, int percentage)
     /* [previous][next][first][last][top][bottom][index][help]  */
  71 {
  72     if (!g->terminal_progress || g->terminal_percentage == percentage)
  73         return;
  74 
  75     g->terminal_percentage = percentage;
  76 
  77     if (percentage < 0)
  78         fprintf (stdout, ESC_STR "]9;4;0" ESC_STR "\\");
  79     else
  80         fprintf (stdout, ESC_STR "]9;4;1;%d" ESC_STR "\\", percentage);
  81     (void) fflush (stdout);
  82 }
  83 
  84 /* --------------------------------------------------------------------------------------------- */
  85 
  86 static cb_ret_t
  87 gauge_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
  88 {
  89     WGauge *g = GAUGE (w);
  90     const int *colors;
  91 
  92     switch (msg)
  93     {
  94     case MSG_DRAW:
  95         colors = widget_get_colors (w);
  96         widget_gotoyx (w, 0, 0);
  97         if (!g->shown)
  98         {
  99             tty_setcolor (colors[DLG_COLOR_NORMAL]);
 100             tty_printf ("%*s", w->rect.cols, "");
 101             gauge_report_to_terminal (g, -1);
 102         }
 103         else
 104         {
 105             int gauge_len;
 106             int percentage, columns;
 107             int total = g->max;
 108             int done = g->current;
 109 
 110             if (total <= 0 || done < 0)
 111             {
 112                 done = 0;
 113                 total = 100;
 114             }
 115             if (done > total)
 116                 done = total;
 117             while (total > 65535)
 118             {
 119                 total /= 256;
 120                 done /= 256;
 121             }
 122 
 123             gauge_len = w->rect.cols - 7;  // 7 positions for percentage
 124 
 125             percentage = (200 * done / total + 1) / 2;
 126             columns = (2 * gauge_len * done / total + 1) / 2;
 127             tty_print_char ('[');
 128             if (g->from_left_to_right)
 129             {
 130                 tty_setcolor (CORE_GAUGE_COLOR);
 131                 tty_printf ("%*s", columns, "");
 132                 tty_setcolor (colors[DLG_COLOR_NORMAL]);
 133                 tty_printf ("%*s] %3d%%", gauge_len - columns, "", percentage);
 134             }
 135             else
 136             {
 137                 tty_setcolor (colors[DLG_COLOR_NORMAL]);
 138                 tty_printf ("%*s", gauge_len - columns, "");
 139                 tty_setcolor (CORE_GAUGE_COLOR);
 140                 tty_printf ("%*s", columns, "");
 141                 tty_setcolor (colors[DLG_COLOR_NORMAL]);
 142                 tty_printf ("] %3d%%", percentage);
 143             }
 144 
 145             gauge_report_to_terminal (g, percentage);
 146         }
 147         return MSG_HANDLED;
 148 
 149     case MSG_DESTROY:
 150         gauge_report_to_terminal (g, -1);
 151         return widget_default_callback (w, sender, msg, parm, data);
 152 
 153     default:
 154         return widget_default_callback (w, sender, msg, parm, data);
 155     }
 156 }
 157 
 158 /* --------------------------------------------------------------------------------------------- */
 159 /*** public functions ****************************************************************************/
 160 /* --------------------------------------------------------------------------------------------- */
 161 
 162 WGauge *
 163 gauge_new (int y, int x, int cols, gboolean shown, int max, int current,
     /* [previous][next][first][last][top][bottom][index][help]  */
 164            gboolean from_left_to_right, gboolean terminal_progress)
 165 {
 166     WRect r = { y, x, 1, cols };
 167     WGauge *g;
 168     Widget *w;
 169 
 170     g = g_new (WGauge, 1);
 171     w = WIDGET (g);
 172     widget_init (w, &r, gauge_callback, NULL);
 173 
 174     g->shown = shown;
 175     if (max == 0)
 176         max = 1;  // I do not like division by zero :)
 177     g->max = max;
 178     g->current = current;
 179     g->from_left_to_right = from_left_to_right;
 180     g->terminal_progress = terminal_progress;
 181     g->terminal_percentage = -1;
 182 
 183     return g;
 184 }
 185 
 186 /* --------------------------------------------------------------------------------------------- */
 187 
 188 void
 189 gauge_set_value (WGauge *g, int max, int current)
     /* [previous][next][first][last][top][bottom][index][help]  */
 190 {
 191     if (g->current == current && g->max == max)
 192         return;  // Do not flicker
 193 
 194     if (max == 0)
 195         max = 1;  // I do not like division by zero :)
 196     g->current = current;
 197     g->max = max;
 198     widget_draw (WIDGET (g));
 199 }
 200 
 201 /* --------------------------------------------------------------------------------------------- */
 202 
 203 void
 204 gauge_show (WGauge *g, gboolean shown)
     /* [previous][next][first][last][top][bottom][index][help]  */
 205 {
 206     if (g->shown != shown)
 207     {
 208         g->shown = shown;
 209         widget_draw (WIDGET (g));
 210     }
 211 }
 212 
 213 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */