1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2 
3 #include "vt_model.h"
4 
5 #include <pobl/bl_mem.h> /* malloc/free */
6 #include <pobl/bl_debug.h>
7 #include <pobl/bl_util.h>
8 
9 /* --- global functions --- */
10 
vt_model_init(vt_model_t * model,u_int num_cols,u_int num_rows)11 int vt_model_init(vt_model_t *model, u_int num_cols, u_int num_rows) {
12   u_int count;
13 
14   if (num_rows == 0 || num_cols == 0) {
15     return 0;
16   }
17 
18   model->num_rows = num_rows;
19   model->num_cols = num_cols;
20 
21   if ((model->lines = calloc(sizeof(vt_line_t), model->num_rows)) == NULL) {
22 #ifdef DEBUG
23     bl_warn_printf(BL_DEBUG_TAG "calloc() failed.\n");
24 #endif
25 
26     return 0;
27   }
28 
29   for (count = 0; count < model->num_rows; count++) {
30     if (!vt_line_init(&model->lines[count], model->num_cols)) {
31       return 0;
32     }
33   }
34 
35   model->beg_row = 0;
36 
37   return 1;
38 }
39 
vt_model_final(vt_model_t * model)40 void vt_model_final(vt_model_t *model) {
41   u_int count;
42 
43   for (count = 0; count < model->num_rows; count++) {
44     vt_line_final(&model->lines[count]);
45   }
46 
47   free(model->lines);
48 }
49 
vt_model_reset(vt_model_t * model)50 void vt_model_reset(vt_model_t *model) {
51   u_int count;
52 
53   for (count = 0; count < model->num_rows; count++) {
54     vt_line_reset(&model->lines[count]);
55     vt_line_set_updated(&model->lines[count]);
56   }
57 }
58 
vt_model_resize(vt_model_t * model,u_int num_cols,u_int num_rows,u_int slide)59 int vt_model_resize(vt_model_t *model, u_int num_cols, u_int num_rows, u_int slide) {
60   int new_row;
61   u_int count;
62   u_int copy_rows;
63   vt_line_t *lines_p;
64 
65   if (num_cols == 0 || num_rows == 0) {
66     return 0;
67   }
68 
69   if (num_cols == model->num_cols && num_rows == model->num_rows) {
70     /* not resized */
71 
72     return 0;
73   }
74 
75   if ((lines_p = calloc(sizeof(vt_line_t), num_rows)) == NULL) {
76     return 0;
77   }
78 
79   if (model->num_rows - slide > num_rows) {
80     copy_rows = num_rows;
81   } else {
82     copy_rows = model->num_rows - slide;
83   }
84 
85   /* updating existing lines. */
86   for (new_row = 0; new_row < copy_rows; new_row++) {
87     vt_line_init(&lines_p[new_row], num_cols);
88     vt_line_copy(&lines_p[new_row], vt_model_get_line(model, slide));
89     slide++;
90     vt_line_set_modified_all(&lines_p[new_row]);
91     lines_p[new_row].is_modified = 2; /* XXX See set_real_modified() in vt_line.c */
92   }
93 
94   /* freeing old data. */
95   for (count = 0; count < model->num_rows; count++) {
96     vt_line_final(&model->lines[count]);
97   }
98   free(model->lines);
99   model->lines = lines_p;
100 
101   /* update empty lines. */
102   for (; new_row < num_rows; new_row++) {
103     vt_line_init(&lines_p[new_row], num_cols);
104     vt_line_set_modified_all(&lines_p[new_row]);
105   }
106 
107   model->num_rows = num_rows;
108   model->num_cols = num_cols;
109 
110   model->beg_row = 0;
111 
112   return 1;
113 }
114 
vt_model_get_num_filled_rows(vt_model_t * model)115 u_int vt_model_get_num_filled_rows(vt_model_t *model) {
116   u_int filled_rows;
117 
118   for (filled_rows = model->num_rows; filled_rows > 0; filled_rows--) {
119 #if 1
120     /*
121      * XXX
122      * This is problematic, since the value of 'slide' can be incorrect when
123      * cursor is located at the line which contains white spaces alone.
124      */
125     if (vt_line_get_num_filled_chars_except_sp(vt_model_get_line(model, filled_rows - 1)) > 0)
126 #else
127     if (!vt_line_is_empty(vt_model_get_line(model, filled_rows - 1)))
128 #endif
129     {
130       break;
131     }
132   }
133 
134   return filled_rows;
135 }
136 
vt_model_end_row(vt_model_t * model)137 int vt_model_end_row(vt_model_t *model) { return model->num_rows - 1; }
138 
vt_model_get_line(vt_model_t * model,int row)139 vt_line_t *vt_model_get_line(vt_model_t *model, int row) {
140   if (row < 0 || model->num_rows <= row) {
141 #ifdef __DEBUG
142     bl_debug_printf(BL_DEBUG_TAG " row %d is out of range.\n", row);
143 #endif
144 
145     return NULL;
146   }
147 
148   if (model->beg_row + row < model->num_rows) {
149     return &model->lines[model->beg_row + row];
150   } else {
151     return &model->lines[model->beg_row + row - model->num_rows];
152   }
153 }
154 
vt_model_scroll_upward(vt_model_t * model,u_int size)155 void vt_model_scroll_upward(vt_model_t *model, u_int size) {
156   if (size > model->num_rows) {
157     size = model->num_rows;
158   }
159 
160   if (model->beg_row + size >= model->num_rows) {
161     model->beg_row = model->beg_row + size - model->num_rows;
162   } else {
163     model->beg_row += size;
164   }
165 }
166 
vt_model_scroll_downward(vt_model_t * model,u_int size)167 void vt_model_scroll_downward(vt_model_t *model, u_int size) {
168   if (size > model->num_rows) {
169     size = model->num_rows;
170   }
171 
172   if (model->beg_row < size) {
173     model->beg_row = model->num_rows - (size - model->beg_row);
174   } else {
175     model->beg_row -= size;
176   }
177 }
178 
179 #ifdef DEBUG
180 
vt_model_dump(vt_model_t * model)181 void vt_model_dump(vt_model_t *model) {
182   int row;
183   vt_line_t *line;
184 
185   for (row = 0; row < model->num_rows; row++) {
186     line = vt_model_get_line(model, row);
187 
188     if (vt_line_is_modified(line)) {
189       bl_msg_printf("!%.2d-%.2d", vt_line_get_beg_of_modified(line),
190                     vt_line_get_end_of_modified(line));
191     } else {
192       bl_msg_printf("      ");
193     }
194 
195     bl_msg_printf("[%.2d %.2d]", line->num_filled_chars, vt_line_get_num_filled_cols(line));
196 
197     vt_str_dump(line->chars, line->num_filled_chars);
198   }
199 }
200 
201 #endif
202