bool sc_goto(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); zathura_jumplist_save(zathura); if (t != 0) { /* add offset */ t += zathura_document_get_page_offset(zathura->document); page_set(zathura, t - 1); } else if (argument->n == TOP) { page_set(zathura, 0); } else if (argument->n == BOTTOM) { page_set(zathura, zathura_document_get_number_of_pages(zathura->document) - 1); } /* adjust horizontal position */ GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); cb_view_hadjustment_changed(hadjustment, zathura); zathura_jumplist_add(zathura); return false; }
bool sc_goto(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); zathura_jumplist_add(zathura); if (t != 0) { /* add offset */ t += zathura_document_get_page_offset(zathura->document); page_set(zathura, t - 1); } else if (argument->n == TOP) { page_set(zathura, 0); } else if (argument->n == BOTTOM) { page_set(zathura, zathura_document_get_number_of_pages(zathura->document) - 1); } zathura_jumplist_add(zathura); return false; }
bool sc_rotate(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(zathura->document != NULL, false); const unsigned int page_number = zathura_document_get_current_page_number(zathura->document); int angle = 90; if (argument != NULL && argument->n == ROTATE_CCW) { angle = 270; } /* update rotate value */ t = (t == 0) ? 1 : t; unsigned int rotation = zathura_document_get_rotation(zathura->document); zathura_document_set_rotation(zathura->document, (rotation + angle * t) % 360); /* update scale */ girara_argument_t new_argument = { zathura_document_get_adjust_mode(zathura->document), NULL }; sc_adjust_window(zathura->ui.session, &new_argument, NULL, 0); /* render all pages again */ render_all(zathura); page_set(zathura, page_number); return false; }
bool sc_toggle_page_mode(girara_session_t* session, girara_argument_t* UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t)) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; if (zathura->document == NULL) { girara_notify(session, GIRARA_WARNING, _("No document opened.")); return false; } unsigned int page_id = zathura_document_get_current_page_number(zathura->document); int pages_per_row = 1; girara_setting_get(zathura->ui.session, "pages-per-row", &pages_per_row); int value = 1; if (pages_per_row == 1) { value = zathura->shortcut.toggle_page_mode.pages; } else { zathura->shortcut.toggle_page_mode.pages = pages_per_row; } girara_setting_set(zathura->ui.session, "pages-per-row", &value); adjust_view(zathura); page_set(zathura, page_id); render_all(zathura); refresh_view(zathura); return true; }
bool cb_unknown_command(girara_session_t* session, const char* input) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); g_return_val_if_fail(input != NULL, false); zathura_t* zathura = session->global.data; if (zathura->document == NULL) { return false; } /* check for number */ const size_t size = strlen(input); for (size_t i = 0; i < size; i++) { if (g_ascii_isdigit(input[i]) == FALSE) { return false; } } zathura_jumplist_add(zathura); page_set(zathura, atoi(input) - 1); zathura_jumplist_add(zathura); return true; }
bool sc_jumplist(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t)) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); zathura_jump_t* jump = NULL; switch(argument->n) { case FORWARD: zathura_jumplist_save(zathura); zathura_jumplist_forward(zathura); jump = zathura_jumplist_current(zathura); break; case BACKWARD: zathura_jumplist_save(zathura); zathura_jumplist_backward(zathura); jump = zathura_jumplist_current(zathura); break; } if (jump != NULL) { page_set(zathura, jump->page); const double s = zathura_document_get_scale(zathura->document); position_set_delayed(zathura, jump->x * s, jump->y * s); } return false; }
bool cmd_bookmark_open(girara_session_t* session, girara_list_t* argument_list) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; if (zathura->document == NULL) { girara_notify(session, GIRARA_ERROR, _("No document opened.")); return false; } const unsigned int argc = girara_list_size(argument_list); if (argc != 1) { girara_notify(session, GIRARA_ERROR, _("Invalid number of arguments given.")); return false; } const char* bookmark_name = girara_list_nth(argument_list, 0); zathura_bookmark_t* bookmark = zathura_bookmark_get(zathura, bookmark_name); if (bookmark == NULL) { girara_notify(session, GIRARA_ERROR, _("No such bookmark: %s"), bookmark_name); return false; } zathura_jumplist_add(zathura); page_set(zathura, bookmark->page - 1); if (bookmark->x != DBL_MIN && bookmark->y != DBL_MIN) { position_set(zathura, bookmark->x, bookmark->y); } zathura_jumplist_add(zathura); return true; }
space_t space_alloc(void) { space_t space = frame_new(); uint32_t *map = (void*) TMP_SRC; /* clear new space */ page_set(TMP_SRC, page_fmt(space, PF_PRES | PF_RW)); memclr(map, PAGESZ); /* set recursive mapping */ map[PGE_MAP >> 22] = page_fmt(space, PF_PRES | PF_RW); return space; }
bool sc_navigate(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); int number_of_pages = zathura_document_get_number_of_pages(zathura->document); int new_page = zathura_document_get_current_page_number(zathura->document); bool scroll_wrap = false; girara_setting_get(session, "scroll-wrap", &scroll_wrap); bool columns_per_row_offset = false; girara_setting_get(session, "advance-pages-per-row", &columns_per_row_offset); int offset = 1; if (columns_per_row_offset == true) { girara_setting_get(session, "pages-per-row", &offset); } t = (t == 0) ? (unsigned int) offset : t; if (argument->n == NEXT) { if (scroll_wrap == false) { new_page = new_page + t; } else { new_page = (new_page + t) % number_of_pages; } } else if (argument->n == PREVIOUS) { if (scroll_wrap == false) { new_page = new_page - t; } else { new_page = (new_page + number_of_pages - t) % number_of_pages; } } if (!scroll_wrap) { if (new_page <= 0) { new_page = 0; } else if (new_page >= number_of_pages) { new_page = number_of_pages - 1; } } page_set(zathura, new_page); return false; }
bool sc_navigate(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); int number_of_pages = zathura_document_get_number_of_pages(zathura->document); int new_page = zathura_document_get_current_page_number(zathura->document); bool scroll_wrap = false; girara_setting_get(session, "scroll-wrap", &scroll_wrap); bool columns_per_row_offset = false; girara_setting_get(session, "advance-pages-per-row", &columns_per_row_offset); int offset = 1; if (columns_per_row_offset == true) { girara_setting_get(session, "pages-per-row", &offset); } t = (t == 0) ? (unsigned int) offset : t; if (argument->n == NEXT) { if (scroll_wrap == false) { new_page = new_page + t; } else { new_page = (new_page + t) % number_of_pages; } } else if (argument->n == PREVIOUS) { if (scroll_wrap == false) { new_page = new_page - t; } else { new_page = (new_page + number_of_pages - t) % number_of_pages; } } if ((new_page < 0 || new_page >= number_of_pages) && !scroll_wrap) { return false; } page_set(zathura, new_page); /* adjust horizontal position */ GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); cb_view_hadjustment_changed(hadjustment, zathura); return false; }
static void *heap_valloc(uintptr_t size) { static uintptr_t brk = KERNEL_HEAP; int i; if (brk + size >= KERNEL_HEAP_END) { /* out of memory */ /* print analysis */ for (i = 0; i < 16; i++) { debug_printf("%d: %d\n", i, analysis[i]); } debug_panic("out of virtual memory"); return NULL; } else { page_set(brk, page_fmt(frame_new(), PF_PRES | PF_RW)); mem_alloc(brk, size, PF_PRES | PF_RW); brk += size; return (void*) (brk - size); } }
void kcall(struct thread *image) { if (image->flags & TF_USER) { // perform syscall // save user state image->usr_eip = image->eip; image->usr_esp = image->useresp; // switch to system mode image->ss = 0x21; image->ds = 0x21; image->cs = 0x19; image->flags &= ~TF_USER; // restore system state image->eip = image->sys_eip; image->useresp = image->sys_esp; return; } switch (image->eax) { case KCALL_SPAWN: { int id = thread_new(); if (id == -1) { // failure to create new thread image->eax = -1; break; } struct thread *thread = thread_get(id); struct t_info *state = (void*) image->ebx; // initialize thread state thread->useresp = state->regs.esp; thread->esp = (uintptr_t) &thread->num; thread->ss = 0x21; thread->ds = 0x21; thread->cs = 0x19; thread->eflags = image->eflags; thread->eip = state->regs.eip; thread->ebp = state->regs.ebp; thread->esi = state->regs.esi; thread->edi = state->regs.edi; thread->edx = state->regs.edx; thread->ecx = state->regs.ecx; thread->ebx = state->regs.ebx; thread->eax = state->regs.eax; // add to scheduler queue thread->state = TS_QUEUED; schedule_push(thread); image->eax = id; break; } case KCALL_REAP: { struct thread *target = thread_get(image->ebx); if (target->state != TS_PAUSED) { image->eax = TE_STATE; } else { if (image->ecx) { save_info((void*) image->ecx, target); } image->eax = 0; thread_kill(target); } break; } case KCALL_GETTID: { image->eax = image->id; break; } case KCALL_YIELD: { thread_save(image); schedule_push(image); image->state = TS_QUEUED; break; } case KCALL_PAUSE: { struct thread *target = thread_get(image->ebx); if (image->ebx == (uint32_t) -1) target = image; if (!target) { image->eax = TE_EXIST; } else switch (target->state) { case TS_RUNNING: // pause (normal, from running) thread_save(target); target->state = TS_PAUSED; image->eax = 0; break; case TS_QUEUED: // pause (normal, from queued) schedule_remv(target); target->state = TS_PAUSED; image->eax = 0; break; case TS_WAITING: // pause (waiting) event_remv(target->id, target->event); target->state = TS_PAUSEDW; image->eax = 0; break; default: // invalid state transition image->eax = TE_STATE; break; } break; } case KCALL_RESUME: { struct thread *target = thread_get(image->ebx); if (!target) { image->eax = TE_EXIST; } else switch (target->state) { case TS_PAUSED: // resume thread by scheduling schedule_push(target); target->state = TS_QUEUED; image->eax = 0; break; case TS_PAUSEDW: // resume thread by entering wait queue event_wait(target->id, target->event); target->state = TS_WAITING; image->eax = 0; break; default: image->eax = TE_STATE; break; } break; } case KCALL_GETSTATE: { struct thread *target = thread_get(image->ebx); if (image->ebx == (uint32_t) -1) target = image; if (!target) { image->eax = TE_EXIST; } else if (target->state != TS_PAUSED && target->state != TS_PAUSEDW && target != image) { image->eax = TE_STATE; } else { save_info((void*) image->ecx, target); image->eax = 0; } break; } case KCALL_SETSTATE: { struct thread *target = thread_get(image->ebx); if (image->ebx == (uint32_t) -1) target = image; if (!target) { image->eax = TE_EXIST; } else switch (target->state) { case TS_PAUSED: case TS_PAUSEDW: case TS_RUNNING: { struct t_info *src = (void*) image->ecx; if (src->flags & TF_DEAD) { // kill thread if (target->state == TS_RUNNING) { thread_save(target); target->state = TS_PAUSED; } // notify reaper dead_push(target); } if (target->pctx != src->pctx) { // change paging contexts pctx_load(src->pctx); } // save thread state target->pctx = src->pctx; target->flags = src->flags; target->fault = src->fault; if (target->state != TS_RUNNING) { // save register state target->edi = src->regs.edi; target->esi = src->regs.esi; target->ebp = src->regs.ebp; target->useresp = src->regs.esp; target->ebx = src->regs.ebx; target->edx = src->regs.edx; target->ecx = src->regs.ecx; target->eax = src->regs.eax; target->eip = src->regs.eip; target->eflags = src->regs.eflags; // save MMX/SSE state if (!target->fxdata) target->fxdata = heap_alloc(512); memcpy(target->fxdata, &src->regs.fxdata[0], 512); } target->usr_eip = src->usr_ip; target->usr_esp = src->usr_sp; image->eax = 0; break; } default: image->eax = TE_STATE; break; } break; } case KCALL_GETDEAD: { if (dead_peek()) { struct thread *dead = dead_pull(); image->eax = dead->id; } else { thread_save(image); image->state = TS_PAUSED; dead_wait(image); } break; } case KCALL_GETFAULT: { if (fault_peek()) { struct thread *fault = fault_pull(); image->eax = fault->id; } else { thread_save(image); image->state = TS_PAUSED; fault_wait(image); } break; } case KCALL_WAIT: { image->eax = event_wait(image->id, image->ebx); break; } case KCALL_RESET: { if (image->ebx < 240) { extern int irqstate[EV_COUNT]; irqstate[image->ebx] = 0; irq_unmask(image->ebx); } image->eax = 0; break; } case KCALL_SYSRET: { // save system state image->sys_eip = image->eip; image->sys_esp = image->useresp; // perform return value swap-in image->eax = image->ebp; // switch to usermode image->ss = 0x33; image->ds = 0x33; image->cs = 0x2B; image->flags |= TF_USER; // restore user state image->eip = image->usr_eip; image->useresp = image->usr_esp; break; } case KCALL_NEWPCTX: { image->eax = pctx_new(); break; } case KCALL_FREEPCTX: { image->eax = pctx_free(image->ebx); break; } case KCALL_SETFRAME: { page_set(image->ebx, page_fmt(image->ecx, page_get(image->ebx))); image->eax = 0; break; } case KCALL_SETFLAGS: { page_set(image->ebx, page_fmt(page_ufmt(page_get(image->ebx)), image->ecx)); image->eax = 0; break; } case KCALL_GETFRAME: { uint32_t off = image->ebx & 0xFFF; uint32_t page = image->ebx & ~0xFFF; image->eax = page_ufmt(page_get(page)) | off; break; } case KCALL_GETFLAGS: { image->eax = page_get(image->ebx) & PF_MASK; break; } case KCALL_NEWFRAME: { uint64_t frame = frame_new(); image->eax = frame & 0xFFFFFFFF; image->ebx = frame >> 32ULL; break; } case KCALL_FREEFRAME: { frame_free(image->ebx); image->eax = 0; break; } case KCALL_TAKEFRAME: { image->eax = 1; break; } default: { debug_printf("warning: unimplemented kcall %d\n", image->eax); image->eax = -1; break; } } }
void synctex_highlight_rects(zathura_t* zathura, unsigned int page, girara_list_t** rectangles) { const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document); for (unsigned int p = 0; p != number_of_pages; ++p) { GObject* widget = G_OBJECT(zathura->pages[p]); g_object_set(widget, "draw-links", FALSE, "search-results", rectangles[p], NULL); if (p == page) { g_object_set(widget, "search-current", 0, NULL); } } document_draw_search_results(zathura, true); girara_list_t* rect_list = rectangles[page]; if (rect_list == NULL || girara_list_size(rect_list) == 0) { girara_debug("No rectangles for the given page. Jumping to page %u.", page); page_set(zathura, page); return; } bool search_hadjust = true; girara_setting_get(zathura->ui.session, "search-hadjust", &search_hadjust); /* compute the position of the center of the page */ double pos_x = 0; double pos_y = 0; page_number_to_position(zathura->document, page, 0.5, 0.5, &pos_x, &pos_y); /* correction to center the current result */ /* NOTE: rectangle is in viewport units, already scaled and rotated */ unsigned int cell_height = 0; unsigned int cell_width = 0; zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width); unsigned int doc_height = 0; unsigned int doc_width = 0; zathura_document_get_document_size(zathura->document, &doc_height, &doc_width); /* Need to adjust rectangle to page scale and orientation */ zathura_page_t* doc_page = zathura_document_get_page(zathura->document, page); zathura_rectangle_t* rect = girara_list_nth(rect_list, 0); if (rect == NULL) { girara_debug("List of rectangles is broken. Jumping to page %u.", page); page_set(zathura, page); return; } zathura_rectangle_t rectangle = recalc_rectangle(doc_page, *rect); /* compute the center of the rectangle, which will be aligned to the center of the viewport */ double center_x = (rectangle.x1 + rectangle.x2) / 2; double center_y = (rectangle.y1 + rectangle.y2) / 2; pos_y += (center_y - (double)cell_height/2) / (double)doc_height; if (search_hadjust == true) { pos_x += (center_x - (double)cell_width/2) / (double)doc_width; } /* move to position */ girara_debug("Jumping to page %u position (%f, %f).", page, pos_x, pos_y); zathura_jumplist_add(zathura); position_set(zathura, pos_x, pos_y); zathura_jumplist_add(zathura); }
bool sc_bisect(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); unsigned int number_of_pages, cur_page, prev_page, prev2_page; bool have_prev, have_prev2; zathura_jump_t* prev_jump = NULL; zathura_jump_t* prev2_jump = NULL; number_of_pages= zathura_document_get_number_of_pages(zathura->document); cur_page = zathura_document_get_current_page_number(zathura->document); prev_page = prev2_page = 0; have_prev = have_prev2 = false; /* save position at current jump point */ zathura_jumplist_save(zathura); /* process arguments */ int direction; if (t > 0 && t <= number_of_pages) { /* jump to page t, and bisect between cur_page and t */ page_set(zathura, t-1); zathura_jumplist_add(zathura); if (t-1 > cur_page) { direction = BACKWARD; } else { direction = FORWARD; } } else if (argument != NULL) { direction = argument->n; } else { return false; } cur_page = zathura_document_get_current_page_number(zathura->document); if (zathura_jumplist_has_previous(zathura)) { /* If there is a previous jump, get its page */ zathura_jumplist_backward(zathura); prev_jump = zathura_jumplist_current(zathura); if (prev_jump) { prev_page = prev_jump->page; have_prev = true; } if (zathura_jumplist_has_previous(zathura)) { /* If there is a second previous jump, get its page. */ zathura_jumplist_backward(zathura); prev2_jump = zathura_jumplist_current(zathura); if (prev2_jump) { prev2_page = prev2_jump->page; have_prev2 = true; } zathura_jumplist_forward(zathura); } zathura_jumplist_forward(zathura); } /* now, we are back at the initial jump. prev_page and prev2_page contain the pages for previous and second previous jump if they exist. */ /* bisect */ switch(direction) { case FORWARD: if (have_prev && cur_page <= prev_page) { /* add a new jump point */ if (cur_page < prev_page) { page_set(zathura, (cur_page + prev_page)/2); zathura_jumplist_add(zathura); } } else if (have_prev2 && cur_page <= prev2_page) { /* save current position at previous jump point */ if (cur_page < prev2_page) { zathura_jumplist_backward(zathura); zathura_jumplist_save(zathura); zathura_jumplist_forward(zathura); page_set(zathura, (cur_page + prev2_page)/2); zathura_jumplist_save(zathura); } } else { /* none of prev_page or prev2_page comes after cur_page */ page_set(zathura, (cur_page + number_of_pages - 1)/2); zathura_jumplist_add(zathura); } break; case BACKWARD: if (have_prev && prev_page <= cur_page) { /* add a new jump point */ if (prev_page < cur_page) { page_set(zathura, (cur_page + prev_page)/2); zathura_jumplist_add(zathura); } } else if (have_prev2 && prev2_page <= cur_page) { /* save current position at previous jump point */ if (prev2_page < cur_page) { zathura_jumplist_backward(zathura); zathura_jumplist_save(zathura); zathura_jumplist_forward(zathura); page_set(zathura, (cur_page + prev2_page)/2); zathura_jumplist_save(zathura); } } else { /* none of prev_page or prev2_page comes before cur_page */ page_set(zathura, cur_page/2); zathura_jumplist_add(zathura); } break; } /* adjust horizontal position */ GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); cb_view_hadjustment_changed(hadjustment, zathura); return false; }
bool sc_jumplist(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t)) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); /* if no jumps in the jumplist */ if (zathura->jumplist.size == 0) { return true; } double x = zathura_document_get_position_x(zathura->document); double y = zathura_document_get_position_y(zathura->document); zathura_jump_t* jump = NULL; zathura_jump_t* prev_jump = zathura_jumplist_current(zathura); bool go_to_current = false; if (zathura_jumplist_has_next(zathura) == false || zathura_jumplist_has_previous(zathura) == false) { if (x == prev_jump->x && y == prev_jump->y) { go_to_current = false; } else { go_to_current = true; } } switch(argument->n) { case FORWARD: if (go_to_current == true && zathura_jumplist_has_previous(zathura) == false) { jump = zathura_jumplist_current(zathura); } else { zathura_jumplist_forward(zathura); jump = zathura_jumplist_current(zathura); } break; case BACKWARD: if (go_to_current == true && zathura_jumplist_has_next(zathura) == false) { jump = zathura_jumplist_current(zathura); } else { zathura_jumplist_backward(zathura); jump = zathura_jumplist_current(zathura); } break; } if (jump == prev_jump) { if ((zathura_jumplist_has_previous(zathura) == false && argument->n == BACKWARD) || (zathura_jumplist_has_next(zathura) == false && argument->n == FORWARD)) { jump = NULL; } } if (jump != NULL) { page_set(zathura, jump->page); position_set(zathura, jump->x, jump->y); } return false; }
bool sc_bisect(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); const unsigned int num_pages = zathura_document_get_number_of_pages(zathura->document); const unsigned int cur_page = zathura_document_get_current_page_number(zathura->document); /* process arguments */ int direction; if (t > 0 && t <= num_pages) { /* bisect between cur_page and t */ t -= 1; if (t == cur_page) { /* nothing to do */ return false; } else if (t > cur_page) { zathura->bisect.start = cur_page; zathura->bisect.end = t; direction = BACKWARD; } else { zathura->bisect.start = t; zathura->bisect.end = cur_page; direction = FORWARD; } } else if (argument != NULL) { direction = argument->n; /* setup initial bisect range */ zathura_jump_t* jump = zathura_jumplist_current(zathura); if (jump == NULL) { girara_debug("bisecting between first and last page because there are no jumps"); zathura->bisect.start = 0; zathura->bisect.end = num_pages - 1; } else if (jump->page != cur_page || jump->page != zathura->bisect.last_jump) { girara_debug("last jump doesn't match up, starting new bisecting"); zathura->bisect.start = 0; zathura->bisect.end = num_pages - 1; unsigned int prev_page; if (direction == FORWARD) { prev_page = num_pages - 1; } else { prev_page = 0; } /* check if we have previous jumps */ if (zathura_jumplist_has_previous(zathura) == true) { zathura_jumplist_backward(zathura); jump = zathura_jumplist_current(zathura); if (jump != NULL) { prev_page = jump->page; } zathura_jumplist_forward(zathura); } zathura->bisect.start = MIN(prev_page, cur_page); zathura->bisect.end = MAX(prev_page, cur_page); zathura->bisect.last_jump = cur_page; } } else { return false; } girara_debug("bisecting between %d and %d, at %d", zathura->bisect.start, zathura->bisect.end, cur_page); if (zathura->bisect.start == zathura->bisect.end) { /* nothing to do */ return false; } unsigned int next_page = cur_page; unsigned int next_start = zathura->bisect.start; unsigned int next_end = zathura->bisect.end; /* here we have next_start <= next_page <= next_end */ /* bisect step */ switch(direction) { case FORWARD: if (cur_page != zathura->bisect.end) { next_page = (cur_page + zathura->bisect.end) / 2; if (next_page == cur_page) { ++next_page; } next_start = cur_page; } break; case BACKWARD: if (cur_page != zathura->bisect.start) { next_page = (cur_page + zathura->bisect.start) / 2; if (next_page == cur_page) { --next_page; } next_end = cur_page; } break; } if (next_page == cur_page) { /* nothing to do */ return false; } girara_debug("bisecting between %d and %d, jumping to %d", zathura->bisect.start, zathura->bisect.end, next_page); zathura->bisect.last_jump = next_page; zathura->bisect.start = next_start; zathura->bisect.end = next_end; zathura_jumplist_add(zathura); page_set(zathura, next_page); zathura_jumplist_add(zathura); return false; }
struct thread *init(struct multiboot *mboot, uint32_t mboot_magic) { struct process *idle, *init; struct module *module; struct memory_map *mem_map; size_t mem_map_count, i, addr; uintptr_t boot_image_size; void *boot_image; struct elf32_ehdr *init_image; struct elf32_ehdr *dl_image; /* initialize debugging output */ debug_init(); debug_printf("Rhombus Operating System Kernel v0.8a\n"); /* check multiboot header */ if (mboot_magic != 0x2BADB002) { debug_panic("bootloader is not multiboot compliant"); } /* touch pages for the kernel heap */ for (i = KSPACE; i < KERNEL_HEAP_END; i += SEGSZ) { page_touch(i); } /* identity map kernel boot frames */ for (i = KSPACE + KERNEL_BOOT; i < KSPACE + KERNEL_BOOT_END; i += PAGESZ) { page_set(i, page_fmt(i - KSPACE, PF_PRES | PF_RW)); } /* parse the multiboot memory map to find the size of memory */ mem_map = (void*) (mboot->mmap_addr + KSPACE); mem_map_count = mboot->mmap_length / sizeof(struct memory_map); for (i = 0; i < mem_map_count; i++) { if (mem_map[i].type == 1 && mem_map[i].base_addr_low <= 0x100000) { for (addr = 0; addr < mem_map[i].length_low; addr += PAGESZ) { frame_add(mem_map[i].base_addr_low + addr); } } } /* bootstrap process 0 (idle) */ idle = process_alloc(); idle->space = cpu_get_cr3(); idle->user = 0; /* fork process 1 (init) and switch */ init = process_clone(idle, NULL); process_switch(init); /* get multiboot module information */ if (mboot->mods_count < 3) { if (mboot->mods_count < 2) { if (mboot->mods_count < 1) { debug_panic("no boot or init or dl modules found"); } else { debug_panic("no boot or dl modules found"); } } else { debug_panic("no dl module found"); } } module = (void*) (mboot->mods_addr + KSPACE); init_image = (void*) (module[0].mod_start + KSPACE); boot_image = (void*) (module[1].mod_start + KSPACE); dl_image = (void*) (module[2].mod_start + KSPACE); boot_image_size = module[1].mod_end - module[1].mod_start; /* move boot image to BOOT_IMAGE in userspace */ mem_alloc(BOOT_IMAGE, boot_image_size, PF_PRES | PF_USER | PF_RW); memcpy((void*) BOOT_IMAGE, boot_image, boot_image_size); /* bootstrap thread 0 in init */ thread_bind(init->thread[0], init); init->thread[0]->useresp = init->thread[0]->stack + SEGSZ; init->thread[0]->esp = (uintptr_t) &init->thread[0]->num; init->thread[0]->ss = 0x23; init->thread[0]->ds = 0x23; init->thread[0]->cs = 0x1B; init->thread[0]->eflags = cpu_get_eflags() | 0x3200; /* IF, IOPL = 3 */ /* bootstrap idle thread */ idle->thread[0] = &__idle_thread; __idle_thread.proc = idle; /* load dl */ if (elf_check_file(dl_image)) { debug_panic("dl.so is not a valid ELF executable"); } elf_load_file(dl_image); /* execute init */ if (elf_check_file(init_image)) { debug_panic("init is not a valid ELF executable"); } elf_load_file(init_image); init->thread[0]->eip = init_image->e_entry; /* register system calls */ int_set_handler(SYSCALL_SEND, syscall_send); int_set_handler(SYSCALL_DONE, syscall_done); int_set_handler(SYSCALL_WHEN, syscall_when); int_set_handler(SYSCALL_RIRQ, syscall_rirq); int_set_handler(SYSCALL_ALSO, syscall_also); int_set_handler(SYSCALL_STAT, syscall_stat); int_set_handler(SYSCALL_PAGE, syscall_page); int_set_handler(SYSCALL_PHYS, syscall_phys); int_set_handler(SYSCALL_FORK, syscall_fork); int_set_handler(SYSCALL_EXIT, syscall_exit); int_set_handler(SYSCALL_STOP, syscall_stop); int_set_handler(SYSCALL_WAKE, syscall_wake); int_set_handler(SYSCALL_GPID, syscall_gpid); int_set_handler(SYSCALL_TIME, syscall_time); int_set_handler(SYSCALL_USER, syscall_user); int_set_handler(SYSCALL_AUTH, syscall_auth); int_set_handler(SYSCALL_PROC, syscall_proc); int_set_handler(SYSCALL_KILL, syscall_kill); int_set_handler(SYSCALL_VM86, syscall_vm86); int_set_handler(SYSCALL_NAME, syscall_name); int_set_handler(SYSCALL_REAP, syscall_reap); /* register fault handlers */ int_set_handler(FAULT_DE, fault_float); int_set_handler(FAULT_DB, fault_generic); int_set_handler(FAULT_NI, fault_generic); int_set_handler(FAULT_BP, fault_generic); int_set_handler(FAULT_OF, fault_generic); int_set_handler(FAULT_BR, fault_generic); int_set_handler(FAULT_UD, fault_generic); int_set_handler(FAULT_NM, fault_nomath); int_set_handler(FAULT_DF, fault_double); int_set_handler(FAULT_CO, fault_float); int_set_handler(FAULT_TS, fault_generic); int_set_handler(FAULT_NP, fault_generic); int_set_handler(FAULT_SS, fault_generic); int_set_handler(FAULT_GP, fault_gpf); int_set_handler(FAULT_PF, fault_page); int_set_handler(FAULT_MF, fault_float); int_set_handler(FAULT_AC, fault_generic); int_set_handler(FAULT_MC, fault_generic); int_set_handler(FAULT_XM, fault_nomath); /* start timer (for preemption) */ timer_set_freq(64); /* initialize FPU/MMX/SSE */ cpu_init_fpu(); /* drop to usermode, scheduling the next thread */ debug_printf("dropping to usermode\n"); return thread_switch(NULL, schedule_next()); }