int main(void) { int data[18]={10,12,31,89,2013,13,42,88,76,45,21,17,75,8,5,2,1,100}; //原始資料 quick(data,0,17); showdata(data); return 0; }
int main(int argc, char **argv) { int fd1, fd2; struct timeval timeout; fd_set readfds; int maxfd; int retval; if (argc != 4) { fprintf(stderr, "usage: %s file file timeout", argv[0]); exit(1); } if ((fd1 = open(argv[1], O_RDONLY)) == -1) oops(argv[1], 2); if ((fd2 = open(argv[2], O_RDONLY)) == -1) oops(argv[2], 3); maxfd = 1 + (fd1 > fd2 ? fd1 : fd2); while (1){ FD_ZERO(&readfds); FD_SET(fd1, &readfds); FD_SET(fd2, &readfds); timeout.tv_sec = atoi(argv[3]); timeout.tv_usec = 0; retval = select(maxfd, &readfds, NULL, NULL, &timeout); if (retval == -1) oops("select", 4); if (retval > 0) { if (FD_ISSET(fd1, &readfds)) showdata(argv[1], fd1); if (FD_ISSET(fd2, &readfds)) showdata(argv[2], fd2); } else printf("no input after %d seconds\n", atoi(argv[3])); } return 0; }
static void processline(char *line) { char *words[32]; char *s; int nwords; nwords = 0; for (s = strtok(line, " \t\r\n"); s; s = strtok(NULL, " \t\r\n")) { if (nwords < 32) { words[nwords++] = s; } } if (nwords==0) { return; } if (!strcasecmp(words[0], "error")) { /* no actual useful messages */ return; } else if (!strcasecmp(words[0], "hello") && nwords==2) { int ver = atoi(words[1]); if (ver != PROTO_VERSION) { fprintf(stderr, "stat161: Wrong protocol version %d\n", ver); exit(1); } } else if (!strcasecmp(words[0], "head") && nwords>1) { setheaders(nwords-1, words+1); } else if (!strcasecmp(words[0], "width") && nwords>1) { setwidths(nwords-1, words+1); } else if (!strcasecmp(words[0], "data") && nwords>1) { showdata(nwords-1, words+1); } else { printf("stat161: Invalid packet (improper header)\n"); } }
static uint8 MDSAD_Read(const uint32 Addr) { uint8 cData; uint8 ds; MDSAD_DRIVE_INFO *pDrive; int32 rtn; cData = 0x00; pDrive = &mdsad_info->drive[mdsad_info->orders.ds]; switch( (Addr & 0x300) >> 8 ) { case MDSAD_READ_ROM: cData = mdsad_rom[Addr & 0xFF]; break; case MDSAD_WRITE_DATA: { if(mdsad_info->datacount == 0) { sim_debug(WR_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " WRITE Start: Drive: %d, Track=%d, Head=%d, Sector=%d\n", PCX, mdsad_info->orders.ds, pDrive->track, mdsad_info->orders.ss, pDrive->sector); sec_offset = calculate_mdsad_sec_offset(pDrive->track, mdsad_info->orders.ss, pDrive->sector); } DBG_PRINT(("MDSAD: " ADDRESS_FORMAT " WRITE-DATA[offset:%06x+%03x]=%02x" NLP, PCX, sec_offset, mdsad_info->datacount, Addr & 0xFF)); mdsad_info->datacount++; if(mdsad_info->datacount < MDSAD_RAW_LEN) sdata.raw[mdsad_info->datacount] = Addr & 0xFF; if(mdsad_info->datacount == (MDSAD_RAW_LEN - 1)) { sim_debug(WR_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " Write Complete\n", PCX); if ((pDrive->uptr == NULL) || (pDrive->uptr->fileref == NULL)) { sim_debug(WR_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " Drive: %d not attached - write ignored.\n", PCX, mdsad_info->orders.ds); return 0x00; } if(mdsad_dev.dctrl & WR_DATA_DETAIL_MSG) showdata(FALSE); switch((pDrive->uptr)->u3) { case IMAGE_TYPE_DSK: if(pDrive->uptr->fileref == NULL) { printf(".fileref is NULL!" NLP); } else { sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); sim_fwrite(sdata.u.data, 1, MDSAD_SECTOR_LEN, (pDrive->uptr)->fileref); } break; case IMAGE_TYPE_CPT: printf("%s: CPT Format not supported" NLP, __FUNCTION__); break; default: printf("%s: Unknown image Format" NLP, __FUNCTION__); break; } } break; } case MDSAD_CTLR_ORDERS: mdsad_info->orders.dd = (Addr & 0x80) >> 7; mdsad_info->orders.ss = (Addr & 0x40) >> 6; mdsad_info->orders.dp = (Addr & 0x20) >> 5; mdsad_info->orders.st = (Addr & 0x10) >> 4; mdsad_info->orders.ds = (Addr & 0x0F); ds = mdsad_info->orders.ds; switch(mdsad_info->orders.ds) { case 0: case 1: mdsad_info->orders.ds = 0; break; case 2: mdsad_info->orders.ds = 1; break; case 4: mdsad_info->orders.ds = 2; break; case 8: mdsad_info->orders.ds = 3; break; } if(mdsad_info->orders.ds != (mdsad_info->orders.ds & 0x03)) { sim_debug(ERROR_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " Controller Orders update drive %x\n", PCX, mdsad_info->orders.ds); mdsad_info->orders.ds &= 0x03; } sim_debug(ORDERS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " Controller Orders: Drive=%x[%x], DD=%d, SS=%d, DP=%d, ST=%d\n", PCX, mdsad_info->orders.ds, ds, mdsad_info->orders.dd, mdsad_info->orders.ss, mdsad_info->orders.dp, mdsad_info->orders.st); /* use latest selected drive */ pDrive = &mdsad_info->drive[mdsad_info->orders.ds]; if(mdsad_info->orders.st == 1) { if(mdsad_info->orders.dp == 0) { sim_debug(SEEK_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " Step out: Track=%d%s\n", PCX, pDrive->track, pDrive->track == 0 ? "[Warn: already at 0]" : ""); if(pDrive->track > 0) /* anything to do? */ pDrive->track--; } else { sim_debug(SEEK_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " Step in: Track=%d%s\n", PCX, pDrive->track, pDrive->track == (MDSAD_TRACKS - 1) ? "[Warn: already at highest track]" : ""); if(pDrive->track < (MDSAD_TRACKS - 1)) /* anything to do? */ pDrive->track++; } } /* always update t0 */ mdsad_info->b_status.t0 = (pDrive->track == 0); break; case MDSAD_CTLR_COMMAND: /* sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " DM=%x\n", PCX, (Addr & 0xF0) >> 4); */ switch(Addr & 0x0F) { case MDSAD_CMD_MOTORS_ON: sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " CMD=Motors On\n", PCX); mdsad_info->com_status.mo = 1; /* Turn motors on */ break; case MDSAD_CMD_NOP: pDrive->sector_wait_count++; switch(pDrive->sector_wait_count) { case 10: { mdsad_info->com_status.sf = 1; mdsad_info->a_status.wi = 0; mdsad_info->a_status.re = 0; mdsad_info->a_status.bd = 0; pDrive->sector_wait_count = 0; pDrive->sector++; if(pDrive->sector >= MDSAD_SECTORS_PER_TRACK) { pDrive->sector = 0; mdsad_info->com_status.ix = 1; } else { mdsad_info->com_status.ix = 0; } break; } case 2: mdsad_info->a_status.wi = 1; break; case 3: mdsad_info->a_status.re = 1; mdsad_info->a_status.bd = 1; break; default: break; } break; case MDSAD_CMD_RESET_SF: sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " CMD=Reset Sector Flag\n", PCX); mdsad_info->com_status.sf = 0; mdsad_info->datacount = 0; break; case MDSAD_CMD_INTR_DIS: sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " CMD=Disarm Interrupt\n", PCX); mdsad_info->int_enable = 0; break; case MDSAD_CMD_INTR_ARM: sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " CMD=Arm Interrupt\n", PCX); mdsad_info->int_enable = 1; break; case MDSAD_CMD_SET_BODY: sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " CMD=Set Body (Diagnostic)\n", PCX); break; case MDSAD_CMD_BEGIN_WR: sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " CMD=Begin Write\n", PCX); break; case MDSAD_CMD_RESET: sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " CMD=Reset Controller\n", PCX); mdsad_info->com_status.mo = 0; /* Turn motors off */ break; default: sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " Unsupported CMD=0x%x\n", PCX, Addr & 0x0F); break; } /* Always Double-Density for now... */ mdsad_info->com_status.dd = 1; cData = (mdsad_info->com_status.sf & 1) << 7; cData |= (mdsad_info->com_status.ix & 1) << 6; cData |= (mdsad_info->com_status.dd & 1) << 5; cData |= (mdsad_info->com_status.mo & 1) << 4; mdsad_info->c_status.sc = pDrive->sector; switch( (Addr & 0xF0) >> 4) { case MDSAD_A_STATUS: /* A-STATUS */ cData |= (mdsad_info->a_status.wi & 1) << 3; cData |= (mdsad_info->a_status.re & 1) << 2; cData |= (mdsad_info->a_status.sp & 1) << 1; cData |= (mdsad_info->a_status.bd & 1); sim_debug(STATUS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " A-Status = <%s %s %s %s %s %s %s %s>\n", PCX, cData & MDSAD_A_SF ? "SF" : " ", cData & MDSAD_A_IX ? "IX" : " ", cData & MDSAD_A_DD ? "DD" : " ", cData & MDSAD_A_MO ? "MO" : " ", cData & MDSAD_A_WI ? "WI" : " ", cData & MDSAD_A_RE ? "RE" : " ", cData & MDSAD_A_SP ? "SP" : " ", cData & MDSAD_A_BD ? "BD" : " "); break; case MDSAD_B_STATUS: /* B-STATUS */ cData |= (mdsad_info->b_status.wr & 1) << 3; cData |= (mdsad_info->b_status.sp & 1) << 2; cData |= (mdsad_info->b_status.wp & 1) << 1; cData |= (mdsad_info->b_status.t0 & 1); sim_debug(STATUS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " B-Status = <%s %s %s %s %s %s %s %s>\n", PCX, cData & MDSAD_B_SF ? "SF" : " ", cData & MDSAD_B_IX ? "IX" : " ", cData & MDSAD_B_DD ? "DD" : " ", cData & MDSAD_B_MO ? "MO" : " ", cData & MDSAD_B_WR ? "WR" : " ", cData & MDSAD_B_SP ? "SP" : " ", cData & MDSAD_B_WP ? "WP" : " ", cData & MDSAD_B_T0 ? "T0" : " "); break; case MDSAD_C_STATUS: /* C-STATUS */ cData |= (mdsad_info->c_status.sc & 0xF); sim_debug(STATUS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " C-Status = <%s %s %s %s %i>\n", PCX, cData & MDSAD_C_SF ? "SF" : " ", cData & MDSAD_C_IX ? "IX" : " ", cData & MDSAD_C_DD ? "DD" : " ", cData & MDSAD_C_MO ? "MO" : " ", cData & MDSAD_C_SC); break; case MDSAD_READ_DATA: /* READ DATA */ { if(mdsad_info->datacount == 0) { sim_debug(RD_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " READ Start: Drive: %d, Track=%d, Head=%d, Sector=%d\n", PCX, mdsad_info->orders.ds, pDrive->track, mdsad_info->orders.ss, pDrive->sector); checksum = 0; sec_offset = calculate_mdsad_sec_offset(pDrive->track, mdsad_info->orders.ss, pDrive->sector); if ((pDrive->uptr == NULL) || (pDrive->uptr->fileref == NULL)) { sim_debug(RD_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " Drive: %d not attached - read ignored.\n", PCX, mdsad_info->orders.ds); return 0xe5; } switch((pDrive->uptr)->u3) { case IMAGE_TYPE_DSK: if(pDrive->uptr->fileref == NULL) { printf(".fileref is NULL!" NLP); } else { sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET); rtn = sim_fread(&sdata.u.data[0], 1, MDSAD_SECTOR_LEN, (pDrive->uptr)->fileref); if (rtn != MDSAD_SECTOR_LEN) { sim_debug(ERROR_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " READ: sim_fread error.\n", PCX); } } break; case IMAGE_TYPE_CPT: printf("%s: CPT Format not supported" NLP, __FUNCTION__); break; default: printf("%s: Unknown image Format" NLP, __FUNCTION__); break; } if(mdsad_dev.dctrl & RD_DATA_DETAIL_MSG) showdata(TRUE); } if(mdsad_info->datacount < MDSAD_SECTOR_LEN) { cData = sdata.u.data[mdsad_info->datacount]; /* Exclusive OR */ checksum ^= cData; /* Rotate Left Circular */ checksum = ((checksum << 1) | ((checksum & 0x80) != 0)) & 0xff; DBG_PRINT(("MDSAD: " ADDRESS_FORMAT " READ-DATA[offset:%06x+%03x]=%02x" NLP, PCX, sec_offset, mdsad_info->datacount, cData)); } else { /* checksum */ cData = checksum; sim_debug(RD_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " READ-DATA: Checksum is: 0x%02x\n", PCX, cData); } mdsad_info->datacount++; break; } default: DBG_PRINT(("MDSAD: " ADDRESS_FORMAT " Invalid DM=%x" NLP, PCX, Addr & 0xF)); break; } break; } return (cData); }
int mix2_decrypt(BUFFER *m) /* 0: ok * -1: error * -2: old message */ { int err = 0; int i,rsalen,rsalen_as_byte; BUFFER *privkey; BUFFER *keyid; BUFFER *dec, *deskey; BUFFER *packetid, *mid, *digest, *addr, *temp, *iv, *ivvec; int type, packet = 0, numpackets = 0, timestamp = 0; BUFFER *body; BUFFER *header, *out; BUFFER *otherdigest, *bodydigest, *antitag, *extract; BUFFER *ttedigest, *hkey, *aes_pre_key, *aes_header_key, *aes_body_key, *aes_tte_key, *aes_iv; BUFFER *trail; privkey = buf_new(); keyid = buf_new(); dec = buf_new(); deskey = buf_new(); packetid = buf_new(); mid = buf_new(); digest = buf_new(); addr = buf_new(); temp = buf_new(); iv = buf_new(); ivvec = buf_new(); body = buf_new(); header = buf_new(); out = buf_new(); otherdigest = buf_new(); bodydigest = buf_new(); antitag = buf_new(); extract = buf_new(); ttedigest = buf_new(); hkey = buf_new(); aes_pre_key = buf_new(); aes_header_key = buf_new(); aes_body_key = buf_new(); aes_tte_key = buf_new(); aes_iv = buf_new(); trail=buf_new(); aes_pre_key->sensitive=1; aes_body_key->sensitive=1; aes_tte_key->sensitive=1; dec->sensitive=1; deskey->sensitive=1; extract->sensitive=1; hkey->sensitive=1; privkey->sensitive=1; buf_get(m, keyid, 16); err = db_getseckey(keyid->data, privkey); if (err == -1) { errlog(WARNING, "rem2.c mix2_decrypt not found keyid %s\n", showdata(keyid,0)); goto end; } rsalen_as_byte=buf_getc(m); switch(rsalen_as_byte) { case 128: /* legacy 1024-bit */ rsalen_as_byte=1; rsalen=128; break; case 2: rsalen_as_byte=2; rsalen=256; break; case 3: rsalen_as_byte=3; rsalen=384; break; case 4: rsalen_as_byte=4; rsalen=512; break; default: err = -1; errlog(NOTICE, "problem with RSA key size encoded as %d\n", rsalen_as_byte); goto end; break; } assert(128==rsalen || 256==rsalen || 384==rsalen || 512==rsalen); buf_get(m, extract, rsalen); /* 3DES key and maybe more */ err = pk_decrypt(extract, privkey); if (err == -1) { err = -1; errlog(NOTICE, "Cannot decrypt message.\n"); goto end; } buf_append(body, m->data + 20 * 512, 10240); buf_get(m, iv, 8); buf_get(m, dec, 328); if (128==rsalen) { if (extract->length != 24) { err = -1; errlog(NOTICE, "Cannot decrypt message - RSA 1024 data has wrong length %d not 24.\n", extract->length); /* If this length is greater someone may have wrongly sent digests under 1k RSA. */ goto end; } buf_cat(deskey, extract); } else { if (extract->length != 216) { err = -1; errlog(NOTICE, "Cannot decrypt message - RSA (large key) data has wrong length %d.\n", extract->length); /* supposed to be: * 3DES * hmac key * hmac-sha256(18*512 headers) * hmac-sha256(body) * hmac-sha256(328-block) * aes_pre_key */ goto end; } /* antitagging measure */ buf_get(extract, deskey, 24); buf_get(extract, hkey, 64); buf_get(extract, otherdigest, 32); buf_get(extract, bodydigest, 32); buf_get(extract, ttedigest, 32); buf_get(extract, aes_pre_key, 32); buf_reset(temp); hmac_sha256(body, hkey, temp); if (!buf_eq(bodydigest, temp)) { errlog(NOTICE, "Antitagging test - wrong digest on body.\n"); err = -1; goto end; } buf_reset(temp); hmac_sha256(dec, hkey, temp); if (!buf_eq(ttedigest, temp)) { errlog(NOTICE, "Antitagging test - wrong digest on 328-block.\n"); err = -1; goto end; } /* There is one more test applicable if packet type is 0. */ derive_aes_keys(aes_pre_key, hkey, aes_header_key, aes_body_key, aes_tte_key, aes_iv); buf_aescrypt(dec, aes_tte_key, aes_iv, DECRYPT); } buf_crypt(dec, deskey, iv, DECRYPT); buf_get(dec, packetid, 16); buf_get(dec, deskey, 24); type = buf_getc(dec); switch (type) { case 0: if (rsalen>=256) { buf_append(antitag, m->data + 2*512, 2*512); buf_reset(temp); hmac_sha256(antitag, hkey, temp); if (!buf_eq(otherdigest, temp)) { errlog(NOTICE, "Antitagging test - wrong digest on later header\n"); err = -1; goto end; } } buf_get(dec, ivvec, 152); buf_get(dec, addr, 80); break; case 1: buf_get(dec, mid, 16); buf_get(dec, iv, 8); break; case 2: packet = buf_getc(dec); numpackets = buf_getc(dec); buf_get(dec, mid, 16); buf_get(dec, iv, 8); break; default: errlog(WARNING, "Unknown message type.\n"); err = -1; goto end; } if (dec->data[dec->ptr] == '0' && dec->data[dec->ptr + 1] == '0' && dec->data[dec->ptr + 2] == '0' && dec->data[dec->ptr + 3] == '0' && dec->data[dec->ptr + 4] == '\0') { dec->ptr += 5; timestamp = buf_geti_lo(dec); } else { errlog(LOG, "Ignoring message without timestamp.\n"); err = -1; goto end; } buf_get(dec, digest, 16); /* digest of this block, but not so far as to include the digest */ dec->length = dec->ptr - 16; /* ignore digest */ dec->ptr = dec->length; /* If using 1024-bit RSA this is the only integrity protection. (It is still present but less important with larger key sizes.) if (!isdigest_md5(dec, digest)) { errlog(NOTICE, "Message digest does not match.\n"); err = -1; goto end; } /* Statistics are gathered in the isnewid() function. */ switch (isnewid(packetid, rsalen_as_byte, timestamp * SECONDSPERDAY)) { case 0: err = -2; /* redundant message */ goto end; case -1: err = -1; /* future timestamp */ goto end; } if (rsalen == 128) { /* skip either 1 or 2 blocks of 512 bytes */ buf_append(trail, m->data + 512, 19*512); } else { /* and AES */ buf_aescrypt(body, aes_body_key, aes_iv, DECRYPT); buf_append(trail, m->data + 2*512, 19*512); buf_aescrypt(trail, aes_header_key, aes_iv, DECRYPT); } switch (type) { case 0: buf_chop(addr); buf_cat(out, addr); buf_nl(out); for (i = 0; i < 19; i++) { buf_reset(header); buf_append(header, trail->data + i * 512, 512); buf_reset(iv); buf_append(iv, ivvec->data + i * 8, 8); buf_crypt(header, deskey, iv, DECRYPT); buf_cat(out, header); } buf_reset(header); buf_pad(header, 512); /* one block of 512 random data regardless of RSA key size */ buf_cat(out, header); buf_reset(iv); buf_append(iv, ivvec->data + 144, 8); buf_crypt(body, deskey, iv, DECRYPT); buf_cat(out, body); mix_pool(out, INTERMEDIATE, -1); break; case 1: buf_crypt(body, deskey, iv, DECRYPT); err = v2body_setlen(body); if (err == -1) goto end; assert(body->ptr == 4); v2body(body); break; case 2: buf_crypt(body, deskey, iv, DECRYPT); v2partial(body, mid, packet, numpackets); break; } end: buf_free(addr); buf_free(aes_body_key); buf_free(aes_header_key); buf_free(aes_iv); buf_free(aes_pre_key); buf_free(aes_tte_key); buf_free(antitag); buf_free(body); buf_free(bodydigest); buf_free(dec); buf_free(deskey); buf_free(digest); buf_free(extract); buf_free(header); buf_free(hkey); buf_free(iv); buf_free(ivvec); buf_free(keyid); buf_free(mid); buf_free(otherdigest); buf_free(out); buf_free(packetid); buf_free(privkey); buf_free(temp); buf_free(trail); buf_free(ttedigest); return (err); }
void main(void) { int key, formon = 0, buton = 1, f2 = 0, busy = 0, v, h, z; char test; int garb; startup(); /* standard startup sequence */ /* Button */ defbutton(100,450,"End"); defbutton(400,450,"Help"); defplate(0,25,"File"); defplate(58,25,"Form"); defplate(150,25,"DOS"); defplate(350,25,"Display"); defplate(450,25,"Clear"); defplate(522,25,"Edit"); defform("50,50,4,test,50,70,8,test2,50,90,6,test3"); initrat(&rat); raton(&rat); do { key = checkinput(); h = rat.horiz; v = rat.verti; if((rat.buttons == LBUTTON && key == PRESS) && (platehit(1,h,v))) { ratoff(&rat); if(formon) { if(f2) busy = 0; removeform(); formon = 0; } else { if(f2) busy = 1; displayform(); formon = 1; } raton(&rat); } if((rat.buttons == RBUTTON && key == PRESS) && (platehit(2,h,v))) { garb = spawnle(P_WAIT,"c:\\command.com",NULL,NULL); if(garb == -1) { shutdown(); perror("\nError"); getch(); exit(1); } } if((rat.buttons == LBUTTON && key == PRESS) && (platehit(3,h,v))) { if(f2 && !busy) { ratoff(&rat); showdata(0,0,testform.fld1); showdata(0,1,testform.fld2); showdata(0,2,testform.fld3); raton(&rat); } } if((rat.buttons == LBUTTON && key == PRESS) && (platehit(4,h,v))) { if(f2 && !busy) { ratoff(&rat); cleanform(0,0,testform.fld1); cleanform(0,1,testform.fld2); cleanform(0,2,testform.fld3); raton(&rat); } } if((rat.buttons == LBUTTON && key == PRESS) && (platehit(5,h,v))) { if(f2 && !busy) { ratoff(&rat); cleanform(0,0,testform.fld1); for(z=0;z<=10;z++) testform.fld1[z]=NULL; test=get_key(); z=0; while(test != ENTER && z < 4) { testform.fld1[z]=test; showdata(0,0,testform.fld1); z++; test=get_key(); } cleanform(0,1,testform.fld2); for(z=0;z<=10;z++) testform.fld2[z]=NULL; test=get_key(); z=0; while(test != ENTER && z < 8) { testform.fld2[z]=test; showdata(0,1,testform.fld2); z++; test=get_key(); } cleanform(0,2,testform.fld3); for(z=0;z<=10;z++) testform.fld3[z]=NULL; test=get_key(); z=0; while(test != ENTER && z < 6) { testform.fld3[z]=test; showdata(0,2,testform.fld3); test=get_key(); z++; } raton(&rat); } } if((rat.buttons == LBUTTON && key == PRESS) && (platehit(0,h,v))) { ratoff(&rat); if(f2) { eraseform(0,WITHOUT); f2 = 0; } else { showform(0,WITHOUT); f2 = 1; } raton(&rat); } if((rat.buttons == RBUTTON && key == HELD) && (checkhit(1,h,v))) { ratoff(&rat); if(buton) { buttonoff(1); buton = 0; } else { buttonon(1); buton = 1; } raton(&rat); } if((rat.buttons == CBUTTON && key == RELEASE) && (checkhit(1,h,v))) { ratoff(&rat); if(buton) { buttonoff(1); buton = 0; } else { buttonon(1); buton = 1; } raton(&rat); } } while(!(((rat.buttons == LBUTTON && key == RELEASE) || (key == ENTER)) && checkhit(0,h,v) || key == ESC)); ratoff(&rat); shutdown(); }
void viewer(Document *dd) { int i, fd, n, oldpage; int nxt; Menu menu, midmenu; Mouse m; Event e; Point dxy, oxy, xy0; Image *tmp; static char *fwditems[] = { "this page", "next page", "exit", 0 }; static char *miditems[] = { "orig size", "zoom in", "fit window", "rotate 90", "upside down", "", "next", "prev", "zerox", "", "reverse", "discard", "write", "", "quit", 0 }; char *s; enum { Eplumb = 4 }; Plumbmsg *pm; doc = dd; /* save global for menuhit */ ul = screen->r.min; einit(Emouse|Ekeyboard); if(doc->addpage != nil) eplumb(Eplumb, "image"); esetcursor(&reading); /* * im is a global pointer to the current image. * eventually, i think we will have a layer between * the display routines and the ps/pdf/whatever routines * to perhaps cache and handle images of different * sizes, etc. */ im = 0; page = reverse ? doc->npage-1 : 0; if(doc->fwdonly) { menu.item = fwditems; menu.gen = 0; menu.lasthit = 0; } else { menu.item = 0; menu.gen = menugen; menu.lasthit = 0; } midmenu.item = miditems; midmenu.gen = 0; midmenu.lasthit = Next; if(doc->docname != nil) setlabel(doc->docname); showpage(page, &menu); esetcursor(nil); nxt = 0; for(;;) { /* * throughout, if doc->fwdonly is set, we restrict the functionality * a fair amount. we don't care about doc->npage anymore, and * all that can be done is select the next page. */ unlockdisplay(display); i = eread(Emouse|Ekeyboard|Eplumb, &e); lockdisplay(display); switch(i){ case Ekeyboard: if(e.kbdc <= 0xFF && isdigit(e.kbdc)) { nxt = nxt*10+e.kbdc-'0'; break; } else if(e.kbdc != '\n') nxt = 0; switch(e.kbdc) { case 'r': /* reverse page order */ if(doc->fwdonly) break; reverse = !reverse; menu.lasthit = doc->npage-1-menu.lasthit; /* * the theory is that if we are reversing the * document order and are on the first or last * page then we're just starting and really want * to view the other end. maybe the if * should be dropped and this should happen always. */ if(page == 0 || page == doc->npage-1) { page = doc->npage-1-page; showpage(page, &menu); } break; case 'w': /* write bitmap of current screen */ esetcursor(&reading); s = writebitmap(); if(s) string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP, display->defaultfont, s); esetcursor(nil); flushimage(display, 1); break; case 'd': /* remove image from working set */ if(doc->rmpage && page < doc->npage) { if(doc->rmpage(doc, page) >= 0) { if(doc->npage < 0) wexits(0); if(page >= doc->npage) page = doc->npage-1; showpage(page, &menu); } } break; case 'q': case 0x04: /* ctrl-d */ wexits(0); case 'u': if(im==nil) break; angle = (angle+180) % 360; showpage(page, &menu); break; case '-': case '\b': case Kleft: if(page > 0 && !doc->fwdonly) { --page; showpage(page, &menu); } break; case '\n': if(nxt) { nxt--; if(nxt >= 0 && nxt < doc->npage && !doc->fwdonly) showpage(page=nxt, &menu); nxt = 0; break; } goto Gotonext; case Kright: case ' ': Gotonext: if(doc->npage && ++page >= doc->npage && !doc->fwdonly) wexits(0); showpage(page, &menu); break; /* * The upper y coordinate of the image is at ul.y in screen->r. * Panning up means moving the upper left corner down. If the * upper left corner is currently visible, we need to go back a page. */ case Kup: if(screen->r.min.y <= ul.y && ul.y < screen->r.max.y){ if(page > 0 && !doc->fwdonly){ --page; showbottom = 1; showpage(page, &menu); } } else { i = Dy(screen->r)/2; if(i > 10) i -= 10; if(i+ul.y > screen->r.min.y) i = screen->r.min.y - ul.y; translate(Pt(0, i)); } break; /* * If the lower y coordinate is on the screen, we go to the next page. * The lower y coordinate is at ul.y + Dy(im->r). */ case Kdown: i = ul.y + Dy(im->r); if(screen->r.min.y <= i && i <= screen->r.max.y){ ul.y = screen->r.min.y; goto Gotonext; } else { i = -Dy(screen->r)/2; if(i < -10) i += 10; if(i+ul.y+Dy(im->r) <= screen->r.max.y) i = screen->r.max.y - Dy(im->r) - ul.y - 1; translate(Pt(0, i)); } break; default: esetcursor(&query); sleep(1000); esetcursor(nil); break; } break; case Emouse: m = e.mouse; switch(m.buttons){ case Left: oxy = m.xy; xy0 = oxy; do { dxy = subpt(m.xy, oxy); oxy = m.xy; translate(dxy); unlockdisplay(display); m = emouse(); lockdisplay(display); } while(m.buttons == Left); if(m.buttons) { dxy = subpt(xy0, oxy); translate(dxy); } break; case Middle: if(doc->npage == 0) break; unlockdisplay(display); n = emenuhit(Middle, &m, &midmenu); lockdisplay(display); if(n == -1) break; switch(n){ case Next: /* next */ if(reverse) page--; else page++; if(page < 0) { if(reverse) return; else page = 0; } if((page >= doc->npage) && !doc->fwdonly) return; showpage(page, &menu); nxt = 0; break; case Prev: /* prev */ if(reverse) page++; else page--; if(page < 0) { if(reverse) return; else page = 0; } if((page >= doc->npage) && !doc->fwdonly && !reverse) return; showpage(page, &menu); nxt = 0; break; case Zerox: /* prev */ zerox(); break; case Zin: /* zoom in */ { double delta; Rectangle r; r = egetrect(Middle, &m); if((rectclip(&r, rectaddpt(im->r, ul)) == 0) || Dx(r) == 0 || Dy(r) == 0) break; /* use the smaller side to expand */ if(Dx(r) < Dy(r)) delta = (double)Dx(im->r)/(double)Dx(r); else delta = (double)Dy(im->r)/(double)Dy(r); esetcursor(&reading); tmp = xallocimage(display, Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)), im->chan, 0, DBlack); if(tmp == nil) { fprint(2, "out of memory during zoom: %r\n"); wexits("memory"); } resample(im, tmp); im = tmp; delayfreeimage(tmp); esetcursor(nil); ul = screen->r.min; redraw(screen); flushimage(display, 1); break; } case Fit: /* fit */ { double delta; Rectangle r; delta = (double)Dx(screen->r)/(double)Dx(im->r); if((double)Dy(im->r)*delta > Dy(screen->r)) delta = (double)Dy(screen->r)/(double)Dy(im->r); r = Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)); esetcursor(&reading); tmp = xallocimage(display, r, im->chan, 0, DBlack); if(tmp == nil) { fprint(2, "out of memory during fit: %r\n"); wexits("memory"); } resample(im, tmp); im = tmp; delayfreeimage(tmp); esetcursor(nil); ul = screen->r.min; redraw(screen); flushimage(display, 1); break; } case Rot: /* rotate 90 */ angle = (angle+90) % 360; showpage(page, &menu); break; case Upside: /* upside-down */ angle = (angle+180) % 360; showpage(page, &menu); break; case Restore: /* restore */ showpage(page, &menu); break; case Reverse: /* reverse */ if(doc->fwdonly) break; reverse = !reverse; menu.lasthit = doc->npage-1-menu.lasthit; if(page == 0 || page == doc->npage-1) { page = doc->npage-1-page; showpage(page, &menu); } break; case Write: /* write */ esetcursor(&reading); s = writebitmap(); if(s) string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP, display->defaultfont, s); esetcursor(nil); flushimage(display, 1); break; case Del: /* delete */ if(doc->rmpage && page < doc->npage) { if(doc->rmpage(doc, page) >= 0) { if(doc->npage < 0) wexits(0); if(page >= doc->npage) page = doc->npage-1; showpage(page, &menu); } } break; case Exit: /* exit */ return; case Empty1: case Empty2: case Empty3: break; }; case Right: if(doc->npage == 0) break; oldpage = page; unlockdisplay(display); n = emenuhit(RMenu, &m, &menu); lockdisplay(display); if(n == -1) break; if(doc->fwdonly) { switch(n){ case 0: /* this page */ break; case 1: /* next page */ showpage(++page, &menu); break; case 2: /* exit */ return; } break; } if(n == doc->npage) return; else page = reverse ? doc->npage-1-n : n; if(oldpage != page) showpage(page, &menu); nxt = 0; break; } break; case Eplumb: pm = e.v; if(pm->ndata <= 0){ plumbfree(pm); break; } if(plumbquit(pm)) exits(nil); if(showdata(pm)) { s = estrdup("/tmp/pageplumbXXXXXXX"); fd = opentemp(s); write(fd, pm->data, pm->ndata); /* lose fd reference on purpose; the file is open ORCLOSE */ } else if(pm->data[0] == '/') { s = estrdup(pm->data); } else { s = emalloc(strlen(pm->wdir)+1+pm->ndata+1); sprint(s, "%s/%s", pm->wdir, pm->data); cleanname(s); } if((i = doc->addpage(doc, s)) >= 0) { page = i; unhide(); showpage(page, &menu); } free(s); plumbfree(pm); break; } } }