int main_loop(t_env *env) { int key; int ret_exec; set_winsize(env); if (env->load == 1) load_game(env); dup_plate(env->last_plate, env->plate, env->size); print_plate(env); while (refresh() == OK && (key = getch()) && clear() == OK) { if (key == KEY_RESIZE && (ret_exec = 0) == 0) set_winsize(env); if (test_window(env)) mvprintw(1, 1, "Affichage impossible"); else { dup_plate(env->last_plate, env->plate, env->size); if (key != KEY_RESIZE) ret_exec = exec_key(env, key); if (ret_exec != 0) return (ret_exec); } print_plate(env); } return (0); }
static void *_pty_thread(void *arg) { int fd = -1; srun_job_t *job = (srun_job_t *) arg; slurm_addr_t client_addr; xsignal_unblock(pty_sigarray); xsignal(SIGWINCH, _handle_sigwinch); if ((fd = slurm_accept_msg_conn(job->pty_fd, &client_addr)) < 0) { error("pty: accept failure: %m"); return NULL; } while (job->state <= SRUN_JOB_RUNNING) { debug2("waiting for SIGWINCH"); poll(NULL, 0, -1); if (winch) { set_winsize(job); _notify_winsize_change(fd, job); } winch = 0; } return NULL; }
static void init_game(t_env *env) { int i; init_scoreboard(env); if ((env->plate = (int **)malloc(sizeof(int *) * env->size)) == NULL) exit(0); if ((env->last_plate = (int **)malloc(sizeof(int *) * env->size)) == NULL) exit(0); i = -1; while (++i < env->size) { if ((env->plate[i] = (int *)ft_memalloc(sizeof(int) * env->size)) == 0) exit(0); if ((env->last_plate[i] = (int *)ft_memalloc(sizeof(int) * env->size)) == 0) exit(0); } pop_new(env->plate, env->size); pop_new(env->plate, env->size); set_winsize(env); }
int srun(int ac, char **av) { int debug_level; env_t *env = xmalloc(sizeof(env_t)); log_options_t logopt = LOG_OPTS_STDERR_ONLY; bool got_alloc = false; slurm_step_io_fds_t cio_fds = SLURM_STEP_IO_FDS_INITIALIZER; slurm_step_launch_callbacks_t step_callbacks; env->stepid = -1; env->procid = -1; env->localid = -1; env->nodeid = -1; env->cli = NULL; env->env = NULL; env->ckpt_dir = NULL; slurm_conf_init(NULL); debug_level = _slurm_debug_env_val(); logopt.stderr_level += debug_level; log_init(xbasename(av[0]), logopt, 0, NULL); _set_exit_code(); if (slurm_select_init(1) != SLURM_SUCCESS ) fatal( "failed to initialize node selection plugin" ); if (switch_init() != SLURM_SUCCESS ) fatal("failed to initialize switch plugin"); init_srun(ac, av, &logopt, debug_level, 1); create_srun_job(&job, &got_alloc, 0, 1); /* * Enhance environment for job */ if (opt.bcast_flag) _file_bcast(); if (opt.cpus_set) env->cpus_per_task = opt.cpus_per_task; if (opt.ntasks_per_node != NO_VAL) env->ntasks_per_node = opt.ntasks_per_node; if (opt.ntasks_per_socket != NO_VAL) env->ntasks_per_socket = opt.ntasks_per_socket; if (opt.ntasks_per_core != NO_VAL) env->ntasks_per_core = opt.ntasks_per_core; env->distribution = opt.distribution; if (opt.plane_size != NO_VAL) env->plane_size = opt.plane_size; env->cpu_bind_type = opt.cpu_bind_type; env->cpu_bind = opt.cpu_bind; env->cpu_freq_min = opt.cpu_freq_min; env->cpu_freq_max = opt.cpu_freq_max; env->cpu_freq_gov = opt.cpu_freq_gov; env->mem_bind_type = opt.mem_bind_type; env->mem_bind = opt.mem_bind; env->overcommit = opt.overcommit; env->slurmd_debug = opt.slurmd_debug; env->labelio = opt.labelio; env->comm_port = slurmctld_comm_addr.port; env->batch_flag = 0; if (opt.job_name) env->job_name = opt.job_name; if (job) { uint16_t *tasks = NULL; slurm_step_ctx_get(job->step_ctx, SLURM_STEP_CTX_TASKS, &tasks); env->select_jobinfo = job->select_jobinfo; env->nodelist = job->nodelist; env->partition = job->partition; /* If we didn't get the allocation don't overwrite the * previous info. */ if (got_alloc) env->nhosts = job->nhosts; env->ntasks = job->ntasks; env->task_count = _uint16_array_to_str(job->nhosts, tasks); env->jobid = job->jobid; env->stepid = job->stepid; env->account = job->account; env->qos = job->qos; env->resv_name = job->resv_name; } if (opt.pty && (set_winsize(job) < 0)) { error("Not using a pseudo-terminal, disregarding --pty option"); opt.pty = false; } if (opt.pty) { struct termios term; int fd = STDIN_FILENO; /* Save terminal settings for restore */ tcgetattr(fd, &termdefaults); tcgetattr(fd, &term); /* Set raw mode on local tty */ cfmakeraw(&term); /* Re-enable output processing such that debug() and * and error() work properly. */ term.c_oflag |= OPOST; tcsetattr(fd, TCSANOW, &term); atexit(&_pty_restore); block_sigwinch(); pty_thread_create(job); env->pty_port = job->pty_port; env->ws_col = job->ws_col; env->ws_row = job->ws_row; } setup_env(env, opt.preserve_env); xfree(env->task_count); xfree(env); _set_node_alias(); memset(&step_callbacks, 0, sizeof(step_callbacks)); step_callbacks.step_signal = launch_g_fwd_signal; /* re_launch: */ relaunch: pre_launch_srun_job(job, 0, 1); launch_common_set_stdio_fds(job, &cio_fds); if (!launch_g_step_launch(job, &cio_fds, &global_rc, &step_callbacks)) { if (launch_g_step_wait(job, got_alloc) == -1) goto relaunch; } fini_srun(job, got_alloc, &global_rc, 0); return (int)global_rc; }
static void _setup_one_job_env(opt_t *opt_local, srun_job_t *job, bool got_alloc) { env_t *env = xmalloc(sizeof(env_t)); uint16_t *tasks = NULL; xassert(job); env->localid = -1; env->nodeid = -1; env->procid = -1; env->stepid = -1; if (opt_local->bcast_flag) _file_bcast(opt_local, job); if (opt_local->cpus_set) env->cpus_per_task = opt_local->cpus_per_task; if (opt_local->ntasks_per_node != NO_VAL) env->ntasks_per_node = opt_local->ntasks_per_node; if (opt_local->ntasks_per_socket != NO_VAL) env->ntasks_per_socket = opt_local->ntasks_per_socket; if (opt_local->ntasks_per_core != NO_VAL) env->ntasks_per_core = opt_local->ntasks_per_core; env->distribution = opt_local->distribution; if (opt_local->plane_size != NO_VAL) env->plane_size = opt_local->plane_size; env->cpu_bind_type = opt_local->cpu_bind_type; env->cpu_bind = opt_local->cpu_bind; env->cpu_freq_min = opt_local->cpu_freq_min; env->cpu_freq_max = opt_local->cpu_freq_max; env->cpu_freq_gov = opt_local->cpu_freq_gov; env->mem_bind_type = opt_local->mem_bind_type; env->mem_bind = opt_local->mem_bind; env->overcommit = opt_local->overcommit; env->slurmd_debug = opt_local->slurmd_debug; env->labelio = opt_local->labelio; env->comm_port = slurmctld_comm_addr.port; if (opt_local->job_name) env->job_name = opt_local->job_name; slurm_step_ctx_get(job->step_ctx, SLURM_STEP_CTX_TASKS, &tasks); env->select_jobinfo = job->select_jobinfo; if (job->pack_node_list) env->nodelist = job->pack_node_list; else env->nodelist = job->nodelist; env->partition = job->partition; /* * If we didn't get the allocation don't overwrite the previous info. */ if (got_alloc) env->nhosts = job->nhosts; env->ntasks = job->ntasks; if (job->pack_ntasks != NO_VAL) env->ntasks = job->pack_ntasks; env->task_count = _uint16_array_to_str(job->nhosts, tasks); if (job->pack_jobid != NO_VAL) env->jobid = job->pack_jobid; else env->jobid = job->jobid; env->stepid = job->stepid; env->account = job->account; env->qos = job->qos; env->resv_name = job->resv_name; if (opt_local->pty && (set_winsize(job) < 0)) { error("Not using a pseudo-terminal, disregarding --pty option"); opt_local->pty = false; } if (opt_local->pty) { struct termios term; int fd = STDIN_FILENO; /* Save terminal settings for restore */ tcgetattr(fd, &termdefaults); tcgetattr(fd, &term); /* Set raw mode on local tty */ cfmakeraw(&term); /* Re-enable output processing such that debug() and * and error() work properly. */ term.c_oflag |= OPOST; tcsetattr(fd, TCSANOW, &term); atexit(&_pty_restore); block_sigwinch(); pty_thread_create(job); env->pty_port = job->pty_port; env->ws_col = job->ws_col; env->ws_row = job->ws_row; } env->env = env_array_copy((const char **) environ); setup_env(env, opt_local->preserve_env); job->env = env->env; xfree(env->task_count); xfree(env); }
void normal() { register u_char c; long n; int flag = FALSE; int type = 0; /* used in some operations to modify type */ int dir = FORWARD; /* search direction */ u_char nchar = NUL; int finish_op; linenr_t Prenum1; char searchbuff[CMDBUFFSIZE]; /* buffer for search string */ FPOS *pos; register char *ptr; int command_busy = FALSE; static linenr_t redo_Quote_nlines; static int redo_Quote_type; static long redo_Quote_col; Prenum = 0; /* * If there is an operator pending, then the command we take this time * will terminate it. Finish_op tells us to finish the operation before * returning this time (unless the operation was cancelled). */ finish_op = (operator != NOP); if (!finish_op && !yankbuffer) opnum = 0; if (vpeekc() == NUL || KeyTyped == TRUE) premsg(NUL, NUL); State = NORMAL_BUSY; c = vgetc(); /* Pick up any leading digits and compute 'Prenum' */ while ((c >= '1' && c <= '9') || (Prenum > 0 && (c == DEL || c == '0'))) { if (c == DEL) Prenum /= 10; else Prenum = Prenum * 10 + (c - '0'); premsg(' ', NUL); c = vgetc(); } /* * If we're in the middle of an operator (including after entering a yank * buffer with ") AND we had a count before the * operator, then that count overrides the current value of Prenum. What * this means effectively, is that commands like "3dw" get turned into * "d3w" which makes things fall into place pretty neatly. * If you give a count before AND after the operator, they are multiplied. */ if (opnum != 0) { if (Prenum) Prenum *= opnum; else Prenum = opnum; opnum = 0; } Prenum1 = (Prenum == 0 ? 1 : Prenum); /* Prenum often defaults to 1 */ premsg(c, NUL); /* * get an additional character if we need one */ if (strchr("@zZtTfF[]rm'`\"", c) || (c == 'v' && Recording == FALSE)) { State = NOMAPPING; nchar = vgetc(); /* no macro mapping for this char */ premsg(c, nchar); } flushbuf(); /* flush the premsg() characters onto the screen so we can see them while the command is being executed */ if (c != 'z') /* the 'z' command gets another character */ { State = NORMAL; script_winsize_pp(); } if (nchar == ESC) { CLEAROP; goto normal_end; } switch (c) { /* * 0: Macros */ case 'v': /* (stop) recording into a named buffer */ CHECKCLEAROP; if (!dorecord(nchar)) CLEAROPBEEP; break; case '@': /* execute a named buffer */ CHECKCLEAROP; while (Prenum1--) if (!doexecbuf(nchar)) { CLEAROPBEEP; break; } break; /* * 1: Screen positioning commands */ case CTRL('D'): flag = TRUE; case CTRL('U'): CHECKCLEAROP; if (Prenum) p_scroll = (Prenum > Rows - 1) ? Rows - 1 : Prenum; n = (p_scroll < Rows) ? p_scroll : Rows - 1; if (flag) { scrollup(n); onedown(n); } else { scrolldown(n); oneup(n); } updateScreen(VALID); break; case CTRL('B'): case K_SUARROW: dir = BACKWARD; case CTRL('F'): case K_SDARROW: CHECKCLEAROP; onepage(dir, Prenum1); break; case CTRL('E'): CHECKCLEAROP; scrollup(Prenum1); updateScreen(VALID); break; case CTRL('Y'): CHECKCLEAROP; scrolldown(Prenum1); updateScreen(VALID); break; case 'z': CHECKCLEAROP; if (isdigit(nchar)) { /* * we misuse some variables to be able to call premsg() */ operator = c; opnum = Prenum; Prenum = nchar - '0'; for (;;) { premsg(' ', NUL); nchar = vgetc(); State = NORMAL; script_winsize_pp(); if (nchar == DEL) Prenum /= 10; else if (isdigit(nchar)) Prenum = Prenum * 10 + (nchar - '0'); else if (nchar == CR) { set_winsize((int)Columns, (int)Prenum, TRUE); break; } else { CLEAROPBEEP; break; } } operator = NOP; break; } if (Prenum) /* line number given */ { if (Prenum > line_count) Curpos.lnum = line_count; else Curpos.lnum = Prenum; } State = NORMAL; script_winsize_pp(); switch (nchar) { case NL: /* put Curpos at top of screen */ case CR: Topline = Prenum; updateScreen(VALID); break; case '.': /* put Curspos in middle of screen */ n = Rows / 2; goto dozcmd; case '-': /* put Curpos at bottom of screen */ n = Rows - 1; /* FALLTHROUGH */ dozcmd: { register linenr_t lp = Prenum; register long l = 0; while ((l < n) && (lp != 0)) { l += plines(lp); Topline = lp; --lp; } } updateScreen(VALID); break; default: CLEAROPBEEP; } break; /* * 2: Control commands */ case ':': if (Quote.lnum) goto dooperator; CHECKCLEAROP; docmdline(NULL); break; case K_HELP: CHECKCLEAROP; help(); break; case CTRL('L'): CHECKCLEAROP; updateScreen(CLEAR); break; case CTRL('G'): CHECKCLEAROP; fileinfo(); break; case K_CCIRCM: /* shorthand command */ CHECKCLEAROPQ; if (getaltfile((int)Prenum, (linenr_t)0, TRUE)) emsg(e_noalt); break; case 'Z': /* write, if changed, and exit */ CHECKCLEAROPQ; if (nchar != 'Z') { CLEAROPBEEP; break; } stuffReadbuff(":x\n"); break; case CTRL(']'): /* :ta to current identifier */ CHECKCLEAROPQ; case '*': /* / to current identifier */ case '#': /* ? to current identifier */ case 'K': /* run program for current identifier */ { register int col; ptr = nr2ptr(Curpos.lnum); col = Curpos.col; /* * skip to start of identifier. */ while (ptr[col] != NUL && !isidchar(ptr[col])) ++col; /* * Back up to start of identifier. This doesn't match the * real vi but I like it a little better and it shouldn't bother * anyone. */ while (col > 0 && isidchar(ptr[col - 1])) --col; if (!isidchar(ptr[col])) { CLEAROPBEEP; break; } if (Prenum) stuffnumReadbuff(Prenum); switch (c) { case '*': stuffReadbuff("/"); break; case '#': stuffReadbuff("?"); break; case 'K': stuffReadbuff(":! "); stuffReadbuff(p_kp); stuffReadbuff(" "); break; default: stuffReadbuff(":ta "); } /* * Now grab the chars in the identifier */ while (isidchar(ptr[col])) { stuffReadbuff(mkstr(ptr[col])); ++col; } stuffReadbuff("\n"); } break; case CTRL('T'): /* backwards in tag stack */ CHECKCLEAROPQ; dotag("", 2, (int)Prenum1); break; /* * Cursor motions */ case 'G': mtype = MLINE; setpcmark(); if (Prenum == 0 || Prenum > line_count) Curpos.lnum = line_count; else Curpos.lnum = Prenum; beginline(TRUE); break; case 'H': case 'M': if (c == 'M') n = Rows / 2; else n = Prenum; mtype = MLINE; Curpos.lnum = Topline; while (n && onedown((long)1)) --n; beginline(TRUE); break; case 'L': mtype = MLINE; Curpos.lnum = Botline - 1; for (n = Prenum; n && oneup((long)1); n--) ; beginline(TRUE); break; case 'l': case K_RARROW: case ' ': mtype = MCHAR; mincl = FALSE; n = Prenum1; while (n--) { if (!oneright()) { if (operator == NOP) beep(); else { if (lineempty(Curpos.lnum)) CLEAROPBEEP; else { mincl = TRUE; if (n) beep(); } } break; } } set_want_col = TRUE; break; case 'h': case K_LARROW: case CTRL('H'): case DEL: mtype = MCHAR; mincl = FALSE; n = Prenum1; while (n--) { if (!oneleft()) { if (operator != DELETE && operator != CHANGE) beep(); else if (Prenum1 == 1) CLEAROPBEEP; break; } } set_want_col = TRUE; break; case '-': flag = TRUE; /* FALLTHROUGH */ case 'k': case K_UARROW: case CTRL('P'): mtype = MLINE; if (!oneup(Prenum1)) CLEAROPBEEP; else if (flag) beginline(TRUE); break; case '+': case CR: flag = TRUE; /* FALLTHROUGH */ case 'j': case K_DARROW: case CTRL('N'): case NL: mtype = MLINE; if (!onedown(Prenum1)) CLEAROPBEEP; else if (flag) beginline(TRUE); break; /* * This is a strange motion command that helps make operators more * logical. It is actually implemented, but not documented in the * real 'vi'. This motion command actually refers to "the current * line". Commands like "dd" and "yy" are really an alternate form of * "d_" and "y_". It does accept a count, so "d3_" works to delete 3 * lines. */ case '_': lineop: mtype = MLINE; if (!onedown((long)(Prenum1 - 1))) CLEAROPBEEP; else if (operator != YANK) /* 'Y' does not move cursor */ beginline(TRUE); break; case '|': mtype = MCHAR; mincl = TRUE; beginline(FALSE); if (Prenum > 0) coladvance((colnr_t)(Prenum - 1)); Curswant = Prenum - 1; break; /* * Word Motions */ case 'B': type = 1; /* FALLTHROUGH */ case 'b': case K_SLARROW: mtype = MCHAR; mincl = FALSE; set_want_col = TRUE; if (bck_word(Prenum1, type)) CLEAROPBEEP; break; case 'E': type = 1; /* FALLTHROUGH */ case 'e': mincl = TRUE; goto dowrdcmd; case 'W': type = 1; /* FALLTHROUGH */ case 'w': case K_SRARROW: mincl = FALSE; flag = TRUE; /* * This is a little strange. To match what the real vi does, we * effectively map 'cw' to 'ce', and 'cW' to 'cE', provided that we are * not on a space or a TAB. This seems * impolite at first, but it's really more what we mean when we say * 'cw'. */ if (operator == CHANGE && (n = gcharCurpos()) != ' ' && n != TAB && n != NUL) { mincl = TRUE; flag = FALSE; } dowrdcmd: mtype = MCHAR; set_want_col = TRUE; if (flag) n = fwd_word(Prenum1, type); else n = end_word(Prenum1, type, operator == CHANGE); if (n) { CLEAROPBEEP; break; } /* * if we do a 'dw' for the last word in a line, we only delete the rest * of the line, not joining the two lines. */ if (operator == DELETE && Prenum1 == 1 && startop.lnum != Curpos.lnum) { Curpos = startop; while (oneright()) ; mincl = TRUE; } break; case '$': mtype = MCHAR; mincl = TRUE; Curswant = 29999; /* so we stay at the end */ if (!onedown((long)(Prenum1 - 1))) { CLEAROPBEEP; break; } if (Quote_block) updateScreen(NOT_VALID); break; case '^': flag = TRUE; /* FALLTHROUGH */ case '0': mtype = MCHAR; mincl = TRUE; beginline(flag); break; /* * 4: Searches */ case '?': case '/': if (!getcmdline(c, (u_char *)searchbuff)) { CLEAROP; break; } mtype = MCHAR; mincl = FALSE; set_want_col = TRUE; n = dosearch(c == '/' ? FORWARD : BACKWARD, searchbuff, FALSE, Prenum1); if (n == 0) CLEAROPBEEP; else if (n == 2) mtype = MLINE; break; case 'N': flag = 1; case 'n': mtype = MCHAR; mincl = FALSE; set_want_col = TRUE; if (!dosearch(0, NULL, flag, Prenum1)) CLEAROPBEEP; break; /* * Character searches */ case 'T': dir = BACKWARD; /* FALLTHROUGH */ case 't': type = 1; goto docsearch; case 'F': dir = BACKWARD; /* FALLTHROUGH */ case 'f': docsearch: mtype = MCHAR; mincl = TRUE; set_want_col = TRUE; if (!searchc(nchar, dir, type, Prenum1)) { CLEAROPBEEP; } break; case ',': flag = 1; /* FALLTHROUGH */ case ';': dir = flag; goto docsearch; /* nchar == NUL, thus repeat previous search */ /* * section or C function searches */ case '[': dir = BACKWARD; /* FALLTHROUGH */ case ']': mtype = MLINE; set_want_col = TRUE; flag = '{'; if (nchar != c) { if (nchar == '[' || nchar == ']') flag = '}'; else { CLEAROPBEEP; break; } } if (dir == FORWARD && operator != NOP) /* e.g. y]] searches for '}' */ flag = '}'; if (!findpar(dir, Prenum1, flag)) { CLEAROPBEEP; } break; case '%': mincl = TRUE; if (Prenum) /* {cnt}% : goto {cnt} percentage in file */ { if (Prenum > 100) CLEAROPBEEP; else { mtype = MLINE; setpcmark(); Curpos.lnum = line_count * Prenum / 100; Curpos.col = 0; } } else /* % : go to matching paren */ { mtype = MCHAR; if ((pos = showmatch()) == NULL) CLEAROPBEEP; else { setpcmark(); Curpos = *pos; set_want_col = TRUE; } } break; case '(': dir = BACKWARD; /* FALLTHROUGH */ case ')': mtype = MCHAR; if (c == ')') mincl = FALSE; else mincl = TRUE; set_want_col = TRUE; if (!findsent(dir, Prenum1)) CLEAROPBEEP; break; case '{': dir = BACKWARD; /* FALLTHROUGH */ case '}': mtype = MCHAR; mincl = FALSE; set_want_col = TRUE; if (!findpar(dir, Prenum1, NUL)) CLEAROPBEEP; break; /* * 5: Edits */ case '.': CHECKCLEAROPQ; if (!start_redo(Prenum)) CLEAROPBEEP; break; case 'u': if (Quote.lnum) goto dooperator; case K_UNDO: CHECKCLEAROPQ; u_undo((int)Prenum1); set_want_col = TRUE; break; case CTRL('R'): CHECKCLEAROPQ; u_redo((int)Prenum1); set_want_col = TRUE; break; case 'U': if (Quote.lnum) goto dooperator; CHECKCLEAROPQ; u_undoline(); set_want_col = TRUE; break; case 'r': if (Quote.lnum) { c = 'c'; goto dooperator; } CHECKCLEAROPQ; n = strlen(nr2ptr(Curpos.lnum)) - Curpos.col; if (n < Prenum1) /* not enough characters to replace */ { CLEAROPBEEP; break; } prep_redo(Prenum1, 'r', NUL, nchar); stuffnumReadbuff(Prenum1); stuffReadbuff("R"); stuffReadbuff(mkstr(nchar)); stuffReadbuff("\033"); break; case 'J': if (Quote.lnum) /* join the quoted lines */ { if (Curpos.lnum > Quote.lnum) { Prenum = Curpos.lnum - Quote.lnum + 1; Curpos.lnum = Quote.lnum; } else Prenum = Quote.lnum - Curpos.lnum + 1; Quote.lnum = 0; } CHECKCLEAROP; if (Prenum <= 1) Prenum = 2; /* default for join is two lines! */ if (Curpos.lnum + Prenum - 1 > line_count) /* beyond last line */ { CLEAROPBEEP; break; } prep_redo(Prenum, 'J', NUL, NUL); dodojoin(Prenum, TRUE, TRUE); break; case 'P': dir = BACKWARD; /* FALLTHROUGH */ case 'p': CHECKCLEAROPQ; prep_redo(Prenum, c, NUL, NUL); doput(dir, Prenum1); break; case CTRL('A'): /* add to number */ case CTRL('S'): /* subtract from number */ CHECKCLEAROPQ; { register int col; char buf[30]; int hex; /* 'x' or 'X': hexadecimal; '0': octal */ static int hexupper = FALSE; /* 0xABC */ ptr = nr2ptr(Curpos.lnum); col = Curpos.col; /* first check if we are on a hexadecimal number */ while (col > 0 && isxdigit(ptr[col])) --col; if (col > 0 && toupper(ptr[col]) == 'X' && ptr[col - 1] == '0' && isxdigit(ptr[col + 1])) --col; /* found hexadecimal number */ else { /* first search forward and then backward for start of number */ col = Curpos.col; while (ptr[col] != NUL && !isdigit(ptr[col])) ++col; while (col > 0 && isdigit(ptr[col - 1])) --col; } if (isdigit(ptr[col]) && u_saveCurpos()) { set_want_col = TRUE; prep_redo(Prenum1, c, NUL, NUL); if (ptr[col] != '0') hex = 0; /* decimal */ else { hex = toupper(ptr[col + 1]); /* assume hexadecimal */ if (hex != 'X' || !isxdigit(ptr[col + 2])) { if (isdigit(hex)) hex = '0'; /* octal */ else hex = 0; /* 0 by itself is decimal */ } } if (!hex && col > 0 && ptr[col - 1] == '-') --col; ptr += col; if (hex == '0') sscanf(ptr, "%lo", &n); else if (hex) sscanf(ptr, "%lx", &n); /* "%X" doesn't work! */ else n = atol(ptr); if (c == CTRL('A')) n += Prenum1; else n -= Prenum1; if (hex == 'X') /* skip the '0x' */ col += 2; Curpos.col = col; do /* delete the old number */ { if (isalpha(c)) { if (isupper(c)) hexupper = TRUE; else hexupper = FALSE; } delchar(FALSE); c = gcharCurpos(); } while (hex ? (hex == '0' ? c >= '0' && c <= '7' : isxdigit(c)) : isdigit(c)); if (hex == '0') sprintf(buf, "0%lo", n); else if (hexupper) sprintf(buf, "%lX", n); else if (hex) sprintf(buf, "%lx", n); else sprintf(buf, "%ld", n); insstr(buf); /* insert the new number */ --Curpos.col; updateline(); } else beep(); } break; /* * 6: Inserts */ case 'A': set_want_col = TRUE; while (oneright()) ; /* FALLTHROUGH */ case 'a': CHECKCLEAROPQ; /* Works just like an 'i'nsert on the next character. */ if (u_saveCurpos()) { if (!lineempty(Curpos.lnum)) incCurpos(); startinsert(c, FALSE, Prenum1); command_busy = TRUE; } break; case 'I': beginline(TRUE); /* FALLTHROUGH */ case 'i': CHECKCLEAROPQ; if (u_saveCurpos()) { startinsert(c, FALSE, Prenum1); command_busy = TRUE; } break; case 'o': if (Quote.lnum) /* switch start and end of quote */ { Prenum = Quote.lnum; Quote.lnum = Curpos.lnum; Curpos.lnum = Prenum; n = Quote.col; Quote.col = Curpos.col; Curpos.col = n; break; } CHECKCLEAROP; if (u_save(Curpos.lnum, (linenr_t)(Curpos.lnum + 1)) && Opencmd(FORWARD, TRUE)) { startinsert('o', TRUE, Prenum1); command_busy = TRUE; } break; case 'O': CHECKCLEAROPQ; if (u_save((linenr_t)(Curpos.lnum - 1), Curpos.lnum) && Opencmd(BACKWARD, TRUE)) { startinsert('O', TRUE, Prenum1); command_busy = TRUE; } break; case 'R': if (Quote.lnum) { c = 'c'; Quote.col = QUOTELINE; goto dooperator; } CHECKCLEAROPQ; if (u_saveCurpos()) { startinsert('R', FALSE, Prenum1); command_busy = TRUE; } break; /* * 7: Operators */ case '~': /* swap case */ /* * if tilde is not an operator and Quoting is off: swap case * of a single character */ if (!p_to && !Quote.lnum) { CHECKCLEAROPQ; if (lineempty(Curpos.lnum)) { CLEAROPBEEP; break; } prep_redo(Prenum, '~', NUL, NUL); if (!u_saveCurpos()) break; for (; Prenum1 > 0; --Prenum1) { if (gcharCurpos() == NUL) break; swapchar(&Curpos); incCurpos(); } set_want_col = TRUE; CHANGED; updateline(); break; } /*FALLTHROUGH*/ case 'd': case 'c': case 'y': case '>': case '<': case '!': case '=': case 'V': dooperator: n = strchr(opchars, c) - opchars + 1; if (n == operator) /* double operator works on lines */ goto lineop; CHECKCLEAROP; if (Prenum != 0) opnum = Prenum; startop = Curpos; operator = n; break; /* * 8: Abbreviations */ /* when quoting the next commands are operators */ case 'S': case 'Y': case 'D': case 'C': case 'x': case 'X': case 's': if (Quote.lnum) { static char trans[] = "ScYyDdCcxdXdsc"; if (isupper(c)) /* uppercase means linewise */ Quote.col = QUOTELINE; c = *(strchr(trans, c) + 1); goto dooperator; } case '&': CHECKCLEAROPQ; if (Prenum) stuffnumReadbuff(Prenum); if (c == 'S') { beginline((int)p_ai); substituting = TRUE; } else if (c == 'Y' && p_ye) c = 'Z'; { static char *(ar[9]) = {"dl", "dh", "d$", "c$", "cl", "c$", "yy", "y$", ":s\r"}; static char *str = "xXDCsSYZ&"; stuffReadbuff(ar[strchr(str, c) - str]); } break; /* * 9: Marks */ case 'm': CHECKCLEAROP; if (!setmark(nchar)) CLEAROPBEEP; break; case '\'': flag = TRUE; /* FALLTHROUGH */ case '`': pos = getmark(nchar, (operator == NOP)); if (pos == (FPOS *)-1) /* jumped to other file */ { if (flag) beginline(TRUE); break; } if (pos != NULL) setpcmark(); cursormark: if (pos == NULL) CLEAROPBEEP; else { Curpos = *pos; if (flag) beginline(TRUE); } mtype = flag ? MLINE : MCHAR; mincl = FALSE; /* ignored if not MCHAR */ set_want_col = TRUE; break; case CTRL('O'): /* goto older pcmark */ Prenum1 = -Prenum1; /* FALLTHROUGH */ case CTRL('I'): /* goto newer pcmark */ CHECKCLEAROPQ; pos = movemark((int)Prenum1); if (pos == (FPOS *)-1) /* jump to other file */ { set_want_col = TRUE; break; } goto cursormark; /* * 10. Buffer setting */ case '"': CHECKCLEAROP; if (isalnum(nchar) || nchar == '.') { yankbuffer = nchar; opnum = Prenum; /* remember count before '"' */ } else CLEAROPBEEP; break; /* * 11. Quoting */ case 'q': case 'Q': case CTRL('Q'): CHECKCLEAROP; Quote_block = FALSE; if (Quote.lnum) /* stop quoting */ { Quote.lnum = 0; updateScreen(NOT_VALID); /* delete the inversion */ } else /* start quoting */ { Quote = Curpos; if (c == 'Q') /* linewise */ Quote.col = QUOTELINE; else if (c == CTRL('Q')) /* blockwise */ Quote_block = TRUE; updateline(); /* start the inversion */ } break; /* * 12. Suspend */ case CTRL('Z'): CLEAROP; Quote.lnum = 0; /* stop quoting */ stuffReadbuff(":st!\r"); /* no autowrite */ break; /* * The end */ case ESC: if (Quote.lnum) { Quote.lnum = 0; /* stop quoting */ updateScreen(NOT_VALID); } default: /* not a known command */ CLEAROPBEEP; break; } /* end of switch on command character */ /* * if we didn't start or finish an operator, reset yankbuffer, unless we * need it later. */ if (!finish_op && !operator && strchr("\"DCYSsXx", c) == NULL) yankbuffer = 0; /* * If an operation is pending, handle it... */ if ((Quote.lnum || finish_op) && operator != NOP) { if (operator != YANK && !Quote.lnum) /* can't redo yank */ { prep_redo(Prenum, opchars[operator - 1], c, nchar); if (c == '/' || c == '?') /* was a search */ { AppendToRedobuff(searchbuff); AppendToRedobuff(NL_STR); } } if (redo_Quote_busy) { startop = Curpos; Curpos.lnum += redo_Quote_nlines - 1; switch (redo_Quote_type) { case 'Q': Quote.col = QUOTELINE; break; case CTRL('Q'): Quote_block = TRUE; break; case 'q': if (redo_Quote_nlines <= 1) Curpos.col += redo_Quote_col; else Curpos.col = redo_Quote_col; break; } if (redo_Quote_col == 29999) { Curswant = 29999; coladvance(29999); } } else if (Quote.lnum) startop = Quote; if (lt(startop, Curpos)) { endop = Curpos; Curpos = startop; } else { endop = startop; startop = Curpos; } nlines = endop.lnum - startop.lnum + 1; if (Quote.lnum || redo_Quote_busy) { if (Quote_block) /* block mode */ { startvcol = getvcol(&startop, 2); n = getvcol(&endop, 2); if (n < startvcol) startvcol = n; /* if '$' was used, get endvcol from longest line */ if (Curswant == 29999) { Curpos.col = 29999; endvcol = 0; for (Curpos.lnum = startop.lnum; Curpos.lnum <= endop.lnum; ++Curpos.lnum) if ((n = getvcol(&Curpos, 3)) > endvcol) endvcol = n; Curpos = startop; } else if (redo_Quote_busy) endvcol = startvcol + redo_Quote_col; else { endvcol = getvcol(&startop, 3); n = getvcol(&endop, 3); if (n > endvcol) endvcol = n; } coladvance(startvcol); } /* * prepare to redo quoting: this is based on the size * of the quoted text */ if (operator != YANK) /* can't redo yank */ { prep_redo(0L, 'q', opchars[operator - 1], NUL); if (Quote_block) redo_Quote_type = CTRL('Q'); else if (Quote.col == QUOTELINE) redo_Quote_type = 'Q'; else redo_Quote_type = 'q'; if (Curswant == 29999) redo_Quote_col = 29999; else if (Quote_block) redo_Quote_col = endvcol - startvcol; else if (nlines > 1) redo_Quote_col = endop.col; else redo_Quote_col = endop.col - startop.col; redo_Quote_nlines = nlines; } mincl = TRUE; if (Quote.col == QUOTELINE) mtype = MLINE; else mtype = MCHAR; redo_Quote_busy = FALSE; /* * Switch quoting off now, so screen updating does * not show inverted text when the screen is redrawn. * With YANK and sometimes with COLON there is no screen redraw, so * it is done here to remove the inverted part. */ Quote.lnum = 0; if (operator == YANK || operator == COLON) updateScreen(NOT_VALID); } set_want_col = 1; if (!mincl && !equal(startop, endop)) oneless = 1; else oneless = 0; switch (operator) { case LSHIFT: case RSHIFT: adjust_lnum(); doshift(operator); break; case DELETE: dodelete(); break; case YANK: doyank(FALSE); break; case CHANGE: dochange(); break; case FILTER: AppendToRedobuff("!\n"); /* strange but necessary */ case INDENT: case COLON: adjust_lnum(); sprintf(IObuff, ":%ld,%ld", (long)startop.lnum, (long)endop.lnum); stuffReadbuff(IObuff); if (operator != COLON) stuffReadbuff("!"); if (operator == INDENT) { stuffReadbuff(p_ep); stuffReadbuff("\n"); } /* docmdline() does the rest */ break; case TILDE: case UPPER: case LOWER: dotilde(); break; case FORMAT: adjust_lnum(); doformat(); break; default: CLEAROPBEEP; } operator = NOP; Quote_block = FALSE; yankbuffer = 0; } normal_end: premsg(-1, NUL); if (restart_edit && operator == NOP && Quote.lnum == 0 && !command_busy && stuff_empty() && yankbuffer == 0) startinsert(NUL, FALSE, 1L); }