?? cellwidget.c
字號:
old_cc = cell; recognize_sample(input, pc->alts, ALTERNATES); pc->ch = input->ch; pc->flags &= ~CELL_VERIFIED; if (pc->ch) pad_cell(cell); /* Copy the alternate ratings and usage stamps before they're overwritten by another call to recognize_sample() */ for (i = 0; i < ALTERNATES && pc->alts[i]; i++) { pc->alt_ratings[i] = pc->alts[i]->rating; pc->alt_used[i] = pc->alts[i]->used; } /* Add a row if this is the last cell */ if (cell == cell_rows * cell_cols - 1) pack_cells(0, cell_cols); } input = NULL; drawing = FALSE;}static gboolean finish_timeout(void)/* Motion timeout for finishing drawing a cell */{ finish_cell(current_cell); render_dirty(); timeout_source = 0; start_timeout(); return FALSE;}static gboolean row_timeout(void)/* Motion timeout for adding a row */{ pack_cells(cell_rows + 1, cell_cols); cell_widget_render(); timeout_source = 0; return FALSE;}static int check_clear(void){ int i; if (is_clear) return TRUE; if (training || (input && input->len)) return FALSE; for (i = 0; i < cell_cols * cell_rows; i++) if (cells[i].ch) return FALSE; return TRUE;}static gboolean is_clear_timeout(void)/* Motion timeout for checking clear state */{ timeout_source = 0; if (is_clear || !check_clear()) return FALSE; /* Show the on-screen keyboard */ show_keys = keyboard_enabled; is_clear = TRUE; pack_cells(1, cell_cols); cell_widget_render(); return FALSE;}static gboolean hold_timeout(void)/* Motion timeout for popping up a hold-click context menu */{ if (potential_hold) { potential_hold = FALSE; stop_drawing(); show_context_menu(1, gtk_get_current_event_time()); } timeout_source = 0; return FALSE;}static void start_timeout(void)/* If a timeout action is approriate for the current situation, start a timeout */{ GSourceFunc func = NULL; if (potential_hold) return; stop_timeout(); if (cross_out) return; /* Events below are not triggered while drawing */ if (!drawing) { if (input) func = (GSourceFunc)finish_timeout; else if (!cells[cell_rows * cell_cols - 1].ch && cells[cell_rows * cell_cols - 2].ch && !training) func = (GSourceFunc)row_timeout; else if (!is_clear && check_clear()) func = (GSourceFunc)is_clear_timeout; } if (func) timeout_source = g_timeout_add(MOTION_TIMEOUT, func, NULL);}static void start_hold(void){ potential_hold = TRUE; if (timeout_source) g_source_remove(timeout_source); timeout_source = g_timeout_add(MOTION_TIMEOUT, (GSourceFunc)hold_timeout, NULL);}void cell_widget_set_cursor(int recreate)/* Set the drawing area cursor to a black box pen cursor or to a blank cursor depending on which is appropriate */{ static char bits[] = { 0xff, 0xff, 0xff }; /* Square cursor */ /*{ 0x02, 0xff, 0x02 };*/ /* Cross cursor */ static GdkCursor *square; GdkPixmap *pixmap; GdkCursor *cursor; /* Ink color changed, recreate cursor */ if (recreate) { if (square) gdk_cursor_unref(square); pixmap = gdk_bitmap_create_from_data(NULL, bits, 3, 3); square = gdk_cursor_new_from_pixmap(pixmap, pixmap, &color_ink, &color_ink, 1, 1); g_object_unref(pixmap); } cursor = square; /* Eraser cursor */ if (eraser || cross_out) { GdkDisplay *display; display = gtk_widget_get_display(drawing_area); cursor = gdk_cursor_new_for_display(display, GDK_CIRCLE); } gdk_window_set_cursor(drawing_area->window, invalid || inserting ? NULL : cursor);}static void stop_drawing(void)/* Ends the current stroke and applies various processing functions */{ Stroke *stroke; if (!drawing) { if (cross_out) { cross_out = FALSE; cell_widget_set_cursor(FALSE); } return; } drawing = FALSE; if (!input || input->len >= STROKES_MAX) return; stroke = input->strokes[input->len - 1]; smooth_stroke(stroke); simplify_stroke(stroke); process_stroke(stroke); render_cell(current_cell); render_sample(input, current_cell); start_timeout();}static void erase_cell(int cell){ if (!training) { clear_cell(cell); render_dirty(); } else { untrain_char(cells[cell].ch); render_cell(cell); }}static void check_cell(double x, double y, GdkDevice *device)/* Check if we have changed to a different cell */{ int cell_x, cell_y, cell, rem_x, rem_y, old_inserting, old_invalid, old_eraser, old_cross_out; /* Stop drawing first */ old_cross_out = cross_out; if (drawing && !cross_out) { int dx, dy; /* Check if we have started the cross-out gesture */ cell_coords(current_cell, &cell_x, &cell_y); cell_x += cell_width / 2; cell_y += cell_height / 2; dx = cell_x - x; dy = cell_y - y; if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; if (dx < cell_width && dy < cell_height) return; cross_out = TRUE; drawing = FALSE; clear_sample(input); input = NULL; erase_cell(current_cell); } /* Is this the eraser tip? */ old_eraser = eraser; eraser = device && device->source == GDK_SOURCE_ERASER; /* Adjust for border */ x--; y--; /* Right-to-left mode inverts the x-axis */ if (right_to_left) x = cell_cols * cell_width - x - 1; /* What cell are we hovering over? */ cell_y = y / cell_height + cell_row_view; cell_x = x / cell_width; cell = cell_cols * cell_y + cell_x; /* Out of bounds or invalid cell */ old_invalid = invalid; invalid = cell_x < 0 || cell_y < 0 || cell_x >= cell_cols || cell_y >= cell_rows || cell_offscreen(cell) || (training && !cells[cell].ch); /* Are we in the insertion hotspot? */ rem_x = x - cell_x * cell_width; rem_y = y - (cell_y - cell_row_view) * cell_height; old_inserting = inserting; inserting = FALSE; if (!cross_out && !eraser && !invalid && !training && !input && (rem_y <= CELL_BORDER * 2 || rem_y > cell_height - CELL_BORDER * 2)) { if (rem_x <= CELL_BORDER + 1) inserting = TRUE; else if (cell < cell_rows * cell_cols - 1 && rem_x > cell_width - CELL_BORDER) { inserting = TRUE; cell++; } } /* Current cell has changed */ old_cc = current_cell; if (current_cell != cell) { current_cell = cell; if (!cross_out) finish_cell(old_cc); } /* We have moved into or out of the insertion hotspot */ if (old_inserting != inserting || old_cc != cell) { if (old_inserting) { dirty_cell(old_cc); dirty_cell(old_cc - 1); } if (inserting) { dirty_cell(current_cell); dirty_cell(current_cell - 1); } } /* Update cursor if necessary */ if (old_invalid != invalid || old_inserting != inserting || old_eraser != eraser || old_cross_out != cross_out) cell_widget_set_cursor(FALSE); render_dirty();}static void unclear(int render)/* Hides the on-screen keyboard and re-renders the cells. FIXME we only need to render dirty cells */{ is_clear = FALSE; if (!show_keys) return; show_keys = FALSE; if (render) cell_widget_render();}static void draw(double x, double y){ Stroke *s; int cx, cy; if (current_cell < 0) return; /* Hide the on-screen keyboard */ unclear(TRUE); /* New character */ if (!input || !input->len) { clear_sample(&cells[current_cell].sample); cells[current_cell].alts[0] = NULL; input = &cells[current_cell].sample; cells[current_cell].sample.ch = cells[current_cell].ch; } /* Allocate a new stroke if we aren't already drawing */ s = input->strokes[input->len - 1]; if (!drawing) { if (input->len >= STROKES_MAX) return; s = input->strokes[input->len++]= stroke_new(0); drawing = TRUE; if (input->len == 1) render_cell(current_cell); } /* Check bounds */ cell_coords(current_cell, &cx, &cy); /* Normalize the input */ x = (x - cx - cell_width / 2) * SCALE / cell_height; y = (y - cy - cell_height / 2) * SCALE / cell_height; draw_stroke(&input->strokes[input->len - 1], x, y);}static void insert_cell(int cell){ int i; /* Find a blank to consume */ for (i = cell; i < cell_rows * cell_cols; i++) if (!cells[i].ch) break; /* Insert a row if necessary */ if (i >= cell_rows * cell_cols - 1) { cells = g_realloc(cells, ++cell_rows * cell_cols * sizeof (Cell)); memset(cells + (cell_rows - 1) * cell_cols, 0, cell_cols * sizeof (Cell)); if (cell_rows > cell_rows_pref) cell_row_view++; } if (i > cell) memmove(cells + cell + 1, cells + cell, (i - cell) * sizeof (Cell)); cells[cell].ch = ' '; cells[cell].alts[0] = NULL; cells[cell].sample.len = 0; cells[cell].sample.ch = 0; pad_cell(cell); pack_cells(0, cell_cols); unclear(FALSE); cell_widget_render();}static void delete_cell(int cell){ int i, rows; clear_cell(cell); memmove(cells + cell, cells + cell + 1, (cell_rows * cell_cols - cell - 1) * sizeof (Cell)); /* Delete a row if necessary */ for (i = 0; i < cell_cols && !cells[(cell_rows - 1) * cell_cols + i].ch; i++);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -