Sunday, March 25, 2018

text based user interface: termbox tutorial - 2. draw box

From the previous post, "text based user interface: termbox tutorial - 1. hello-world.c". I had shown how to add pretty text and how to capsule the text with color.

Now I am showing how to draw box surround the text, same method can be applied to draw a frame.

Let me show the whole code first.

 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
#include <stdio.h>
#include <string.h>
#include "../termbox.h"

static const char chars[] = "hello world";

int main(int argv, char **argc) {
 (void)argc; (void)argv;
 int code = tb_init();
 if (code < 0) {
  fprintf(stderr, "termbox init failed, code: %d\n", code);
  return -1;
 }

 tb_select_input_mode(TB_INPUT_ESC);
 tb_select_output_mode(TB_OUTPUT_NORMAL);
 tb_clear();
 
 int i, j=0;
 
 while(chars[j] != 0) {
   tb_change_cell(j+1, 1, chars[j], TB_BLUE, TB_DEFAULT);
   j++;
 }

 tb_change_cell(0, 0, 0x250C, TB_BLUE, TB_DEFAULT);
 tb_change_cell(12, 0, 0x2510, TB_BLUE, TB_DEFAULT);
 tb_change_cell(0, 2, 0x2514, TB_BLUE, TB_DEFAULT);
 tb_change_cell(12, 2, 0x2518, TB_BLUE, TB_DEFAULT);
 
 for (i = 1; i < 12; ++i) {
  tb_change_cell(i, 0, 0x2500, TB_BLUE, TB_DEFAULT);
  tb_change_cell(i, 2, 0x2500, TB_BLUE, TB_DEFAULT);
 }

 for (i = 1; i < 2; ++i) {
  tb_change_cell(0, i, 0x2502, TB_BLUE, TB_DEFAULT);
  tb_change_cell(12, i, 0x2502, TB_BLUE, TB_DEFAULT);
 }

 tb_present();
 
 while(1) {
  struct tb_event ev;
  tb_poll_event(&ev);

  if (ev.key == TB_KEY_ESC) {
   tb_shutdown();
   return 0;
  }
 }
}

The result:

Simple, but how many lines of codes are needed.
First, I had to print the hello world
while(chars[j] != 0) {
tb_change_cell(j+1, 1, chars[j], TB_BLUE, TB_DEFAULT);
j++;
}

secondly,  draw the four corner using extend ascii
tb_change_cell(0, 0, 0x250C, TB_BLUE, TB_DEFAULT);
tb_change_cell(12, 0, 0x2510, TB_BLUE, TB_DEFAULT);
tb_change_cell(0, 2, 0x2514, TB_BLUE, TB_DEFAULT);
tb_change_cell(12, 2, 0x2518, TB_BLUE, TB_DEFAULT);
0x250C =┌
0x2510 = ┐
0x2514 = └
0x2518 = 
Reference ASCII code for box drawing

thirdly, draw the vertical line on both side.
for (i = 1; i < 2; ++i) {
tb_change_cell(0, i, 0x2502, TB_BLUE, TB_DEFAULT);
tb_change_cell(12, i, 0x2502, TB_BLUE, TB_DEFAULT);
}
0x2502 = │

fourthly, draw the horizontal line for top and bottom.
for (i = 1; i < 12; ++i) {
tb_change_cell(i, 0, 0x2500, TB_BLUE, TB_DEFAULT);
tb_change_cell(i, 2, 0x2500, TB_BLUE, TB_DEFAULT);
}
0x2500 = ─
 
For text UI, you need to do everything in code, compile, then run.
This is the only way you can see the output.
No add and drop features.

Saturday, March 24, 2018

text based user interface: termbox tutorial - 1. hello-world.c

Raspberry PI, Beaglebone, PINE A64, Orange PI ...
All are powerful boards with good GUI.

However, most of time, when we are working these boards, we are using terminal to control the board. Well, monitor is a luxury item to be used.

For people who are not familiar with Bash command might find it hard to start with. On the other hand, people with slight Linux knowledge and c programming will find it good to start simple c programming.

All the distros come with gcc compiler, so everyone can start directly to do programming.

I have one Beaglebone black where I flash it with latest distro. STEP.

I started to search for simple TUI (text based user interface) library, like the old 80 PC.
No definition better than wiki:
"
Text-based user interface (TUI), also called textual user interface or terminal user interface, is a retronym coined sometime after the invention of graphical user interfaces. TUIs display computer graphics in text mode. An advanced TUI may, like GUIs, use the entire screen area and accept mouse and other inputs.
"

After trying a few library, I nailed down to two options: ncurses & termbox.

ncurses:
classic, many tutorials, many references (example code)

termbox:
simple, small, not much example and tutorials.

termbox seem like more grassy and wanted to wear. SOURCE.

There are 3 examples given by the developers.
keyboard.c - show how to interact with keyboard and create box
output.c - show how to create colorful box
paint.c - show how to interact with mouse

it is a very good and intensive example but maybe might not suitable for beginner.

After learning stripping down the code, I come out with hello-world.c
Not much documentation available, it is all about reading the code and testing the function one by one.


 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
#include <stdio.h>
#include <string.h>
#include "../termbox.h"

static const char chars[] = "hello world";

int main(int argv, char **argc) {
 (void)argc; (void)argv;
 int code = tb_init();
 if (code < 0) {
  fprintf(stderr, "termbox init failed, code: %d\n", code);
  return -1;
 }

 tb_select_input_mode(TB_INPUT_ESC);
 tb_select_output_mode(TB_OUTPUT_NORMAL);
 tb_clear();
 
 int j = 0;
 while(chars[j] != 0) {
  tb_change_cell(j, 0, chars[j], TB_WHITE, TB_BLACK);
  j++;
 }
 
 j = 0;
 while(chars[j] != 0) {
  tb_change_cell(j, 1, chars[j], TB_BLACK, TB_DEFAULT);
  j++;
 }
 
 j = 0;
 while(chars[j] != 0) {
  tb_change_cell(j, 2, chars[j], TB_RED, TB_GREEN);
  j++;
 }
 
 j = 0;
 while(chars[j] != 0) {
  tb_change_cell(j, 3, chars[j], TB_GREEN, TB_RED);
  j++;
 }
 
 j = 0;
 while(chars[j] != 0) {
  tb_change_cell(j, 4, chars[j], TB_YELLOW, TB_BLUE);
  j++;
 }
 
 j = 0;
 while(chars[j] != 0) {
  tb_change_cell(j, 5, chars[j], TB_MAGENTA, TB_CYAN);
  j++;
 }
 
 tb_present();
 
 while(1) {
  struct tb_event ev;
  tb_poll_event(&ev);

  if (ev.key == TB_KEY_ESC) {
   tb_shutdown();
   return 0;
  }
 }
}

Output:


main features:
1. tb_select_output_mode(TB_OUTPUT_NORMAL);
This function enable 8 modes of colours to be displayed:
#define TB_DEFAULT 0x00
#define TB_BLACK     0x01
#define TB_RED           0x02
#define TB_GREEN      0x03
#define TB_YELLOW  0x04
#define TB_BLUE           0x05
#define TB_MAGENTA 0x06
#define TB_CYAN          0x07
#define TB_WHITE        0x08

I think the naming is self-explainable.

2. tb_change_cell(x, y, chars[j], TB_WHITE, TB_BLACK);
first argument = x: stand for horizontal
second argument = y: stand for vertical
third argument = chars[j]: character to output
forth argument = TB_WHITE: character is white colour
fifth argument = TB_BLACK: box surround the character is black

3. tb_select_input_mode(TB_INPUT_ESC);
what input is accepted in the program, I am choosing the ESC key input.
Once the ESC key is pressed, the program is exited.

4. tb_poll_event(&ev);
This function polling for input entry from keyboard or from mouse.

5. if (ev.key == TB_KEY_ESC) {
tb_shutdown();
return 0;
     }
Once the program detected the ESC key is pressed, close (tb_shutdown();) the program.