4-gewinnt  1.0.0
Klassiker "4-gewinnt" als Konsolenanwendung
 Alle Datenstrukturen Dateien Funktionen Variablen Makrodefinitionen Seiten
system.c
gehe zur Dokumentation dieser Datei
1 #pragma once
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <string.h>
5 
7 CONSOLE_SCREEN_BUFFER_INFO csbi;
10 
15 void initBuffer(){
16  //set text size maximum and insert a first empty line
17  display.first = NULL;
18  display.last = NULL;
19  display.lineCount = 0;
20  display.vAlign = 0;
21  display.hAlign = 0;
22 }
23 
34 struct LineItem* insertNewLineItem(struct LineItem* prev, struct LineItem* next, int maxTextLength){
35 
36  //allocate memory for line item
37  struct LineItem* newLine = malloc(sizeof(struct LineItem));
38  if (newLine==NULL){
40  }
41 
42  //allocate memory for text
43  newLine->text = malloc(maxTextLength * sizeof(char) * UTF_MULTIPLIER + 1);
44  if (newLine->text==NULL){
46  }
47  newLine->text[0] = '\0';
48 
49  //set line properties
50  newLine->align = (prev!=NULL?prev->align:-1);
51  newLine->byteSize = 0;
52  newLine->length = 0;
53 
54  //relink previous item if given
55  newLine->prev = prev;
56  if (prev!=NULL){
57  newLine->prev->next = newLine;
58  }
59 
60  //chain to next item if given
61  newLine->next = next;
62  if (newLine->next!=NULL){
63  newLine->next->prev = newLine;
64  }
65 
66  //update buffer's first&last pointers
67  if (prev==NULL){
68  display.first = newLine;
69  }
70  if (next==NULL){
71  display.last = newLine;
72  }
73 
74  //update line count and return created line
76  return newLine;
77 }
78 
84 void deleteLineItem(struct LineItem* line, int deleteAllBelow){
85  if (line==NULL){
86  return;
87  }
88 
89  if (!deleteAllBelow){
90  //fix the chain by connecting the following line to the previous
91  if (line->prev!=NULL){
92  line->prev->next = line->next;
93  }
94  } else {
95  //recursive delete requested
96  if (line->next!=NULL){
97  deleteLineItem(line->next,1);
98  }
99  if (line->prev!=NULL){
100  line->prev->next = NULL;
101  }
102  }
103  free(line->text);
104  free(line);
105  display.lineCount--;
106 }
107 
114 int copyChar(char* src, char* dst){
115 
116  //determine the length of the string, see http://en.wikipedia.org/wiki/UTF-8#Description
117  int bytes = 0;
118  char slider = *src;
119  while ((slider & 0x80) == 0x80){
120  slider<<=1;
121  bytes++;
122  }
123  bytes+=!bytes;
124 
125  //copy <bytes>-byte long character
126  int cursor = 0;
127  int length = bytes;
128  while (length--){
129  dst[cursor] = src[cursor];
130  cursor++;
131  }
132 
133  //append null byte and return length of copied data
134  dst[cursor] = '\0';
135  return bytes;
136 }
137 
144 int output(const char* input, ...){
145  if (display.first==NULL || display.last==NULL){
146  exit(EXITCODE_BUFFERERROR);
147  }
148 
149  int result;
150  va_list args;
151  va_start(args, input);
152  va_end(args);
153 
154  //writing to string buffer
155  char buffer[OUTPUT_MAXBUFFER+1];
156  buffer[0] = '\0';
157  result = vsnprintf(buffer, OUTPUT_MAXBUFFER+1, input, args);
158 
159  //keep track of string buffer position and the current line to write to
160  int i = 0;
161  struct LineItem* current = display.last;
162 
163  //loop through buffer and copy to lines
164  while(buffer[i]!='\0'){
165  if (current->length < display.maxTextLength && buffer[i]!='\n'){
166  //line not full yet, copy char
167  int increase = copyChar(buffer+i, current->text+current->byteSize);
168  i += increase;
169  current->byteSize += increase;
170  current->length++;
171  } else {
172  //end line in input: start new line
173  if (buffer[i]=='\n'){
174  i++;
175  }
176  //end line or line full, create new one
177  current->next = insertNewLineItem(current, NULL, display.maxTextLength);
178  current = current->next;
179  }
180  }
181 
182  return result;
183 }
184 
188 void flushBuffer(){
189  if (display.first==NULL || display.last==NULL){
190  exit(EXITCODE_BUFFERERROR);
191  }
192 
193  if(GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ),&csbi)) {
194  consoleBufferWidth = csbi.dwSize.X;
195  consoleBufferHeight = csbi.dwSize.Y;
196  if(!FANCY_FONT){
197  consoleBufferHeight = 23;
198  }
199  }
200 
201  consoleClear();
202 
203  /*### DEBUGGING START ###*/
204 #ifdef DEBUG
205 // static int flushed = 0;
206 // printf("DEBUG: printing %d-line buffer (%d.)",display.lineCount,++flushed);
207 // struct LineItem* debugchain = display.first;
208 // printf(", chain: %d",(int)debugchain);
209 // do {
210 // printf("(%d)->%d",debugchain->length,(int)debugchain->next);
211 // debugchain = debugchain->next;
212 // } while (debugchain!=NULL);
213 // printf(". [END:%d]\n--------------------------------------------------\n",(int)display.last);
214 #endif // DEBUG
215  /*### DEBUGGING END ###*/
216 
217  int i;
218 
219  if (display.vAlign==0){
220  int marginTopSize = consoleBufferHeight/2 - display.lineCount/2 -1;
221  if (marginTopSize > 5){
223  marginTopSize -= 5;
224  }
225  for(i = 0; i < marginTopSize; i++){
226  printf("\n");
227  }
228  }
229 
230  struct LineItem* current = display.first;
231  const int MAX_CHARS_BORDER = 4;
232  const int MAX_BYTES_PER_LINE = (display.maxTextLength + MAX_CHARS_BORDER + 1) * sizeof(char) * UTF_MULTIPLIER;
233  char* collector = malloc(display.lineCount * MAX_BYTES_PER_LINE + 1);
234  if (collector==NULL){
235  exit(EXITCODE_OUTOFMEMORY);
236  }
237  collector[0] = '\0';
238 
239  //calculate left margin for box position
240  int leftMarginSize = 1;
241  if (display.hAlign==0){
242  leftMarginSize = consoleBufferWidth/2 - display.maxTextLength/2 - 1;
243  }
244  char* leftMargin = malloc(sizeof(char)*leftMarginSize+1);
245  if (leftMargin==NULL){
246  exit(EXITCODE_OUTOFMEMORY);
247  }
248  memset(leftMargin,' ',leftMarginSize);
249  leftMargin[leftMarginSize] = '\0';
250 
251  //draw header line
252  strcat(collector,leftMargin);
253  strcat(collector,FONT_DPIPE_TOP_LEFT);
254  for (i = 0; i < display.maxTextLength; i++){
255  strcat(collector,FONT_DPIPE_HORI_BAR);
256  }
257  strcat(collector,FONT_DPIPE_TOP_RIGHT);
258  strcat(collector,"\n");
259 
260  //temporary:
261  printf("%s",collector);
262  collector[0] = '\0';
263 
264  //draw lines
265  int leftPaddingSize = 0;
266  int rightPaddingSize;
267 
268  while (current!=NULL){
269  //padding calculations
270  switch (current->align){
271  case -1:
272  leftPaddingSize = 0;
273  break;
274  case 0:
275  leftPaddingSize = display.maxTextLength/2 - current->length/2;
276  break;
277  case +1:
278  leftPaddingSize = display.maxTextLength - current->length;
279  break;
280  }
281  rightPaddingSize = display.maxTextLength - current->length - leftPaddingSize;
282 
283  //left border and left padding
284  strcat(collector,leftMargin);
285  strcat(collector,FONT_DPIPE_VERT_BAR);
286  strcatRepeat(collector," ",leftPaddingSize);
287  //text
288  strcat(collector,current->text);
289  //right padding and right border
290  strcatRepeat(collector," ",rightPaddingSize);
291  strcat(collector,FONT_DPIPE_VERT_BAR);
292  strcat(collector,"\n");
293  current = current->next;
294  //temporary:
295  printf("%s",collector);
296  collector[0] = '\0';
297  }
298  //draw footer line
299  strcat(collector,leftMargin);
300  strcat(collector,FONT_DPIPE_BOTTOM_LEFT);
301  for (i = 0; i < display.maxTextLength; i++){
302  strcat(collector,FONT_DPIPE_HORI_BAR);
303  }
304  strcat(collector,FONT_DPIPE_BOTTOM_RIGHT);
305 
306  printf("%s",collector);
307  collector[0] = '\0';
308 
309  free(collector);
310 
312  initBuffer();
313 }
314 
319 void startBuffer(int maxTextLength){
320  if (display.first!=NULL || display.last!=NULL){
321  //display not initialized
322  exit(EXITCODE_BUFFERERROR);
323  }
324 
325  if (maxTextLength>consoleBufferWidth-4){
326  //requested buffer too large for window size
327  exit(EXITCODE_WINDOWERROR);
328  }
329 
330  if (maxTextLength<1){
331  exit(EXITCODE_BUFFERERROR);
332  }
333 
334  display.maxTextLength = maxTextLength;
336  display.lineCount = 0;
337  display.first = insertNewLineItem(NULL,NULL,maxTextLength);
338 }
339 
344 void setLineAlign(int align){
345  if(display.last==NULL){
346  exit(EXITCODE_BUFFERERROR);
347  }
348  display.last->align = align;
349 }
350 
356 void printfBanner(int width, int startAt){
357  int length = 57;
358  char* banner[5];
359  banner[0] = "_________ _____ _____ __\n";
360  banner[1] = "__ ____/________________________________ /_ __ // /\n";
361  banner[2] = "_ / _ __ \\_ __ \\_ __ \\ _ \\ ___/ __/ _ // /_\n";
362  banner[3] = "/ /___ / /_/ / / / / / / / __/ /__ / /_ /__ __/\n";
363  banner[4] = "\\____/ \\____//_/ /_//_/ /_/\\___/\\___/ \\__/ /_/ \n";
364  int i;
365  char* bannerBuffer = malloc(sizeof(char)*(width+1)*5);
366  bannerBuffer[0] = '\0';
367  for(i = startAt; i<5; i++){
368  strcatRepeat(bannerBuffer," ",width/2-length/2-1);
369  strcat(bannerBuffer,banner[i]);
370  }
371  printf("%s",bannerBuffer);
372 }
373 
378 void animateBanner(int slideIn){
379  int i = (slideIn ? 5 : 0);
380  while(i >= 0 && i <=5){
381  consoleClear();
383  Sleep(50);
384  i += (slideIn ? -1 : +1);
385  }
386 }
387 
392 void animateBox(int wFrom, int hFrom, int wTo, int hTo){
393  int w = wFrom;
394  int h = hFrom;
395  while(w < wTo){
396  printEmptyBox(w,h);
397  w++;
398  }
399  while(h < hTo){
400  printEmptyBox(w,h);
401  h++;
402  }
403  while(h > hTo){
404  printEmptyBox(w,h);
405  h--;
406  }
407  while(w > wTo){
408  printEmptyBox(w,h);
409  w--;
410  }
411 }
412 
418 void printEmptyBox(int w, int h){
419  int i;
420  startBuffer(w);
421  for (i = 0; i < h; i++) output("\n");
422  flushBuffer();
423 }
424 
429  //should clear the console on most plattforms
430  #ifdef _WIN32
431  //detected windows System (both 32 and 64bit)-->use windows clear
432  system("CLS");
433  #else
434  //detected other (non windows) System-->unse Unix-clear
435  system("clear");
436  #endif
437 
438 }
444 char lower_to_upper(char ch1)
445 {
446  char ch2;
447 
448  if(ch1 >= 'a' && ch1 <= 'z'){
449  ch2 = ('A' + ch1 - 'a');
450  return ch2;
451  }
452  else{
453  ch2 = ch1;
454  return ch2;
455  }
456 }
457 
458 void strcatRepeat(char* target, const char* source, unsigned int howOften){
459  int c;
460  for(c = 0; c < howOften; c++){
461  strcat(target,source);
462  }
463 }
struct OutBuffer display
Definition: system.c:6
int vAlign
Definition: variables.h:25
char * FONT_DPIPE_TOP_LEFT
Definition: fancyfont.c:4
void initBuffer()
Definition: system.c:15
int byteSize
Definition: variables.h:14
char * text
Definition: variables.h:18
struct LineItem * prev
Definition: variables.h:16
struct LineItem * last
Definition: variables.h:22
void setLineAlign(int align)
Definition: system.c:344
const int EXITCODE_OUTOFMEMORY
Definition: variables.h:3
struct LineItem * first
Definition: variables.h:21
char * FONT_DPIPE_BOTTOM_LEFT
Definition: fancyfont.c:6
void printfBanner(int width, int startAt)
Definition: system.c:356
void deleteLineItem(struct LineItem *line, int deleteAllBelow)
Definition: system.c:84
char * FONT_DPIPE_BOTTOM_RIGHT
Definition: fancyfont.c:7
void printEmptyBox(int w, int h)
Definition: system.c:418
int FANCY_FONT
Definition: fancyfont.c:3
const int EXITCODE_BUFFERERROR
Definition: variables.h:4
int length
Definition: variables.h:13
int consoleBufferWidth
Definition: system.c:8
void strcatRepeat(char *target, const char *source, unsigned int howOften)
Definition: system.c:458
struct LineItem * next
Definition: variables.h:17
int consoleBufferHeight
Definition: system.c:9
int maxTextLength
Definition: variables.h:23
void animateBox(int wFrom, int hFrom, int wTo, int hTo)
Definition: system.c:392
char * FONT_DPIPE_VERT_BAR
Definition: fancyfont.c:8
const int OUTPUT_MAXBUFFER
Definition: variables.h:28
void consoleClear()
Definition: system.c:428
int hAlign
Definition: variables.h:26
int output(const char *input,...)
Definition: system.c:144
CONSOLE_SCREEN_BUFFER_INFO csbi
Definition: system.c:7
void startBuffer(int maxTextLength)
Definition: system.c:319
const int UTF_MULTIPLIER
Definition: variables.h:30
char * FONT_DPIPE_HORI_BAR
Definition: fancyfont.c:9
int lineCount
Definition: variables.h:24
void animateBanner(int slideIn)
Definition: system.c:378
void flushBuffer()
Definition: system.c:188
const int EXITCODE_WINDOWERROR
Definition: variables.h:5
struct LineItem * insertNewLineItem(struct LineItem *prev, struct LineItem *next, int maxTextLength)
Definition: system.c:34
int align
Definition: variables.h:15
int copyChar(char *src, char *dst)
Definition: system.c:114
char * FONT_DPIPE_TOP_RIGHT
Definition: fancyfont.c:5
char lower_to_upper(char ch1)
Definition: system.c:444