comparison finch/libgnt/gntwm.c @ 17059:f1abdde52538

A workaround for an ncurses bug about multi-cell characters and panels. (article.gmane.org/gmane.comp.lib.ncurses.bugs/2751)
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Fri, 11 May 2007 21:08:47 +0000
parents 403332494b92
children 4d4a396a478c 3c4280387259
comparison
equal deleted inserted replaced
17058:a19b8d71f868 17059:f1abdde52538
45 static void gnt_wm_win_resized(GntWM *wm, GntNode *node); 45 static void gnt_wm_win_resized(GntWM *wm, GntNode *node);
46 static void gnt_wm_win_moved(GntWM *wm, GntNode *node); 46 static void gnt_wm_win_moved(GntWM *wm, GntNode *node);
47 static void gnt_wm_give_focus(GntWM *wm, GntWidget *widget); 47 static void gnt_wm_give_focus(GntWM *wm, GntWidget *widget);
48 static void update_window_in_list(GntWM *wm, GntWidget *wid); 48 static void update_window_in_list(GntWM *wm, GntWidget *wid);
49 static void shift_window(GntWM *wm, GntWidget *widget, int dir); 49 static void shift_window(GntWM *wm, GntWidget *widget, int dir);
50
51 #ifndef NO_WIDECHAR
52 static int widestringwidth(wchar_t *wide);
53 #endif
50 54
51 static gboolean write_already(gpointer data); 55 static gboolean write_already(gpointer data);
52 static int write_timeout; 56 static int write_timeout;
53 static time_t last_active_time; 57 static time_t last_active_time;
54 static gboolean idle_update; 58 static gboolean idle_update;
134 dst = node->window; 138 dst = node->window;
135 shadow = gnt_widget_has_shadow(widget) ? 1 : 0; 139 shadow = gnt_widget_has_shadow(widget) ? 1 : 0;
136 copywin(src, dst, node->scroll, 0, 0, 0, getmaxy(dst) - 1, getmaxx(dst) - 1, 0); 140 copywin(src, dst, node->scroll, 0, 0, 0, getmaxy(dst) - 1, getmaxx(dst) - 1, 0);
137 } 141 }
138 142
143 /**
144 * The following is a workaround for a bug in most versions of ncursesw.
145 * Read about it in: http://article.gmane.org/gmane.comp.lib.ncurses.bugs/2751
146 *
147 * In short, if a panel hides one cell of a multi-cell character, then the rest
148 * of the characters in that line get screwed. The workaround here is to erase
149 * any such character preemptively.
150 *
151 * Caveat: If a wide character is erased, and the panel above it is moved enough
152 * to expose the entire character, it is not always redrawn.
153 */
154 static void
155 work_around_for_ncurses_bug()
156 {
157 #ifndef NO_WIDECHAR
158 PANEL *panel = NULL;
159 while ((panel = panel_below(panel)) != NULL) {
160 int sx, ex, sy, ey, w, y;
161 cchar_t ch;
162 PANEL *below = panel;
163
164 sx = panel->win->_begx;
165 ex = panel->win->_maxx + sx;
166 sy = panel->win->_begy;
167 ey = panel->win->_maxy + sy;
168
169 while ((below = panel_below(below)) != NULL) {
170 if (sy > below->win->_begy + below->win->_maxy ||
171 ey < below->win->_begy)
172 continue;
173 if (sx > below->win->_begx + below->win->_maxx ||
174 ex < below->win->_begx)
175 continue;
176 for (y = MAX(sy, below->win->_begy); y <= MIN(ey, below->win->_begy + below->win->_maxy); y++) {
177 if (mvwin_wch(below->win, y - below->win->_begy, sx - 1 - below->win->_begx, &ch) != OK)
178 goto right;
179 w = widestringwidth(ch.chars);
180 if (w > 1 && (ch.attr & 1)) {
181 ch.chars[0] = ' ';
182 ch.attr &= ~ A_CHARTEXT;
183 mvwadd_wch(below->win, y - below->win->_begy, sx - 1 - below->win->_begx, &ch);
184 touchline(below->win, y - below->win->_begy, 1);
185 }
186 right:
187 if (mvwin_wch(below->win, y - below->win->_begy, ex + 1 - below->win->_begx, &ch) != OK)
188 continue;
189 w = widestringwidth(ch.chars);
190 if (w > 1 && !(ch.attr & 1)) {
191 ch.chars[0] = ' ';
192 ch.attr &= ~ A_CHARTEXT;
193 mvwadd_wch(below->win, y - below->win->_begy, ex + 1 - below->win->_begx, &ch);
194 touchline(below->win, y - below->win->_begy, 1);
195 }
196 }
197 }
198 }
199 #endif
200 }
201
139 static gboolean 202 static gboolean
140 update_screen(GntWM *wm) 203 update_screen(GntWM *wm)
141 { 204 {
142 if (wm->menu) { 205 if (wm->menu) {
143 GntMenu *top = wm->menu; 206 GntMenu *top = wm->menu;
146 if (node) 209 if (node)
147 top_panel(node->panel); 210 top_panel(node->panel);
148 top = top->submenu; 211 top = top->submenu;
149 } 212 }
150 } 213 }
214 work_around_for_ncurses_bug();
151 update_panels(); 215 update_panels();
152 doupdate(); 216 doupdate();
153 return TRUE; 217 return TRUE;
154 } 218 }
155 219