progress_bar.c
上传用户:knt0001
上传日期:2022-01-28
资源大小:264k
文件大小:5k
源码类别:

Email客户端

开发平台:

C/C++

  1. /**
  2.     eMail is a command line SMTP client.
  3.     Copyright (C) 2001 - 2008 email by Dean Jones
  4.     Software supplied and written by http://www.cleancode.org
  5.     This file is part of eMail.
  6.     eMail is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.     eMail is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.     You should have received a copy of the GNU General Public License
  15.     along with eMail; if not, write to the Free Software
  16.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17. **/
  18. #if HAVE_CONFIG_H
  19. # include "config.h"
  20. #endif
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <unistd.h>
  26. #include <termios.h>
  27. #include <sys/stat.h>
  28. #include <sys/types.h>
  29. #include <sys/ioctl.h>
  30. #include "email.h"
  31. #include "utils.h"
  32. #include "progress_bar.h"
  33. #define SUBLEN 20
  34. #define MIN_WIN_SIZE 50
  35. #define MAX_WIN_SIZE 120
  36. #define BAR_REFRESH  500
  37. /**
  38.  * Truncate the message supplied if 'message' is not NULL.  
  39.  * If message is NULL, return the string "(No Subject)".  
  40.  * If message is not null, truncate it to the right size and 
  41.  * return it to the user via a static variable.
  42. **/
  43. static void
  44. truncateSubject(const char *message, struct prbar *bar)
  45. {
  46. size_t messlen;
  47. bar->subject = xmalloc(SUBLEN);
  48. memset(bar->subject, 0, SUBLEN);
  49. if (message == NULL) {
  50. memcpy(bar->subject, "(No Subject)", 12);
  51. } else {
  52. messlen = strlen(message);
  53. if ((messlen - SUBLEN) > 0) {   /* If message exceeds SUBLEN */
  54. memcpy(bar->subject, message, SUBLEN - 4);
  55. bar->subject[SUBLEN - 4] = '.';
  56. bar->subject[SUBLEN - 3] = '.';
  57. bar->subject[SUBLEN - 2] = '.';
  58. } else {
  59. memcpy(bar->subject, message, messlen);
  60. }
  61. }
  62. }
  63. /**
  64.  * will initialize the prbar struct and return it to the caller
  65.  * this function will set defaults and configure the necessary values
  66. **/
  67. struct prbar *
  68. prbarInit(size_t bytes)
  69. {
  70. struct winsize win_size;
  71. struct prbar *bar;
  72. bar = xmalloc(sizeof(struct prbar));
  73. /* Clear error status if any */
  74. bar->percent = 0;
  75. bar->curr_size = 0;
  76. bar->actual_file_size = bytes;
  77. bar->truncated_file_size = bytes;
  78. /* Set up truncated file size to the nearest KB or MB */
  79. bar->size_type = "Bytes";
  80. if (bar->truncated_file_size > 1024) {      /* Kilobyte */
  81. bar->truncated_file_size /= 1024;
  82. bar->size_type = "KB";
  83. }
  84. if (bar->truncated_file_size > 1024) {      /* Megabyte */
  85. bar->truncated_file_size /= 1024;
  86. bar->size_type = "MB";
  87. }
  88. /* If they don't have stdout, set error */
  89. if (!isatty(STDOUT_FILENO)) {
  90. free(bar);
  91. return NULL;
  92. }
  93. /* Set the size of the terminal */
  94. if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *) &win_size) < 0) {
  95. free(bar);
  96. return NULL;
  97. }
  98. /* If the bar is so small, no point in displaying it */
  99. if (win_size.ws_col < MIN_WIN_SIZE) {
  100. free(bar);
  101. return NULL;
  102. }
  103. if (win_size.ws_col > MAX_WIN_SIZE) {
  104. win_size.ws_col = MAX_WIN_SIZE;
  105. }
  106. /**
  107. * We know that our message has atleast 29 characters in it.  
  108. * We need to subtract the length of the subject and the lenght
  109. * of the size_ent as well so that we may fit the screen.
  110. **/
  111. truncateSubject(Mopts.subject, bar);
  112. bar->bar_size = ((win_size.ws_col - 29) - 
  113. (strlen(bar->subject) + strlen(bar->size_type)));
  114. bar->buf = malloc(bar->bar_size + 1);
  115. memset(bar->buf, ' ', bar->bar_size);
  116. bar->buf[bar->bar_size] = '';
  117. return bar;
  118. }
  119. /**
  120.  * prints a progress bar on the screen determined by the 
  121.  * file size and current size sent to the server. 
  122. **/
  123. void
  124. prbarPrint(size_t bytes, struct prbar *bar)
  125. {
  126. int curr_bar_size;
  127. assert(bar != NULL);
  128. /* Set our current display state */
  129. bar->curr_size += bytes;
  130. bar->percent = (bar->curr_size * 100) / bar->actual_file_size;
  131. /**
  132. * only update the progress bar when
  133. * the size of the file sent is greater
  134. * than BAR_REFRESH  or if we're at 100%
  135. *
  136. * RETHINK: Um, what the hell did I mean here??
  137. **/
  138. if ((bar->percent != 100) && 
  139. ((bar->curr_size - bar->progress) <= BAR_REFRESH)) {
  140. return;
  141. }
  142. bar->progress = bar->curr_size;
  143. curr_bar_size = (bar->curr_size * bar->bar_size) / bar->actual_file_size;
  144. memset(bar->buf, '*', curr_bar_size);
  145. printf("rSending  "%s"  |%s| %3d%% of %2d %s",
  146. bar->subject, bar->buf, bar->percent, 
  147. bar->truncated_file_size, bar->size_type);
  148. if (bar->percent == 100) {
  149. printf("n");
  150. }
  151. fflush(stdout);
  152. }
  153. /**
  154.  * allows a user to destroy the prbar struct properly
  155. **/
  156. void
  157. prbarDestroy(struct prbar *bar)
  158. {
  159. if (bar) {
  160. xfree(bar->buf);
  161. xfree(bar->subject);
  162. xfree(bar);
  163. }
  164. }