summaryrefslogtreecommitdiff
path: root/src/im_counter.cpp
blob: 8c5cd5c40235ba50556a0b892c17ef5204509b54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/** \file
 * \brief Processing Counter
 *
 * See Copyright Notice in im_lib.h
 * $Id: im_counter.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $
 */

#include "im_counter.h"

#include <stdlib.h>
#include <memory.h>


static imCounterCallback iCounterFunc = NULL;
static void* iCounterUserData = NULL;

imCounterCallback imCounterSetCallback(void* user_data, imCounterCallback counter_func)
{
  imCounterCallback old_counter_func = iCounterFunc;
  iCounterFunc = counter_func;
  if (user_data)
    iCounterUserData = user_data;
  return old_counter_func;
}

struct iCounter
{
  int total;
  int current;
  int sequence;
  const char* message;
};

#define MAX_COUNTERS 10
static iCounter iCounterList[MAX_COUNTERS];

int imCounterBegin(const char* title)
{
  static int first = 1;
  if (first)
  {
    memset(iCounterList, 0, MAX_COUNTERS*sizeof(iCounter));
    first = 0;
  }

  if (!iCounterFunc) // counter management is useless
    return -1;

  int counter = -1;
  for (int i = 0; i < MAX_COUNTERS; i++)
  {
    if (iCounterList[i].sequence == 0 ||  // the counter is free
        iCounterList[i].current == 0)     // or we are in a sequence
    {
      counter = i;
      break;
    }
  }

  if (counter == -1) return -1; // too many counters

  iCounter *ct = &iCounterList[counter];

  ct->sequence++;

  if (ct->sequence == 1) // top level counter
    iCounterFunc(counter, iCounterUserData, title, -1);

  return counter;
}

void imCounterEnd(int counter)
{
  if (counter == -1 || !iCounterFunc) return;               // invalid counter

  iCounter *ct = &iCounterList[counter];

  if (ct->sequence == 1) // top level counter
  {
    iCounterFunc(counter, iCounterUserData, NULL, 1001);
    memset(ct, 0, sizeof(iCounter));
  }
  else
    ct->sequence--;
}

int imCounterInc(int counter)
{
  if (counter == -1 || !iCounterFunc)                       // invalid counter
    return 1;

  iCounter *ct = &iCounterList[counter];

  if (ct->sequence == 0 || // counter with no begin or no total
      ct->total == 0)
    return 1;

  const char* msg = NULL;
  if (ct->current == 0)
    msg = ct->message;

  ct->current++;

  int progress = (int)((ct->current * 1000.0f)/ct->total);

  if (ct->current == ct->total)
    ct->current = 0;

  return iCounterFunc(counter, iCounterUserData, msg, progress);
}

int imCounterIncTo(int counter, int count)
{
  if (counter == -1 || !iCounterFunc)                       // invalid counter
    return 1;

  iCounter *ct = &iCounterList[counter];

  if (ct->sequence == 0 || // counter with no begin or no total
      ct->total == 0)
    return 1;

  if (count <= 0) count = 0;
  if (count >= ct->total) count = ct->total;

  ct->current = count;

  const char* msg = NULL;
  if (ct->current == 0)
    msg = ct->message;

  int progress = (int)((ct->current * 1000.0f)/ct->total);

  if (ct->current == ct->total)
    ct->current = 0;

  return iCounterFunc(counter, iCounterUserData, msg, progress);
}

void imCounterTotal(int counter, int total, const char* message)
{
  if (counter == -1 || !iCounterFunc) return;               // invalid counter

  iCounter *ct = &iCounterList[counter];

  if (ct->sequence == 0) return; // counter with no begin

  ct->message = message;
  ct->total = total;
  ct->current = 0;
}