| #include "std.h" |
| #include "dat.h" |
| |
| Ring ring; |
| |
| Key* |
| keyiterate(int skip, char *fmt, ...) |
| { |
| int i; |
| Attr *a; |
| Key *k; |
| va_list arg; |
| |
| va_start(arg, fmt); |
| a = parseattrfmtv(fmt, arg); |
| va_end(arg); |
| |
| for(i=0; i<ring.nkey; i++){ |
| k = ring.key[i]; |
| if(matchattr(a, k->attr, k->privattr)){ |
| if(skip-- > 0) |
| continue; |
| k->ref++; |
| freeattr(a); |
| return k; |
| } |
| } |
| freeattr(a); |
| werrstr("no key found"); |
| return nil; |
| } |
| |
| Key* |
| keylookup(char *fmt, ...) |
| { |
| int i; |
| Attr *a; |
| Key *k; |
| va_list arg; |
| |
| va_start(arg, fmt); |
| a = parseattrfmtv(fmt, arg); |
| va_end(arg); |
| |
| for(i=0; i<ring.nkey; i++){ |
| k = ring.key[i]; |
| if(matchattr(a, k->attr, k->privattr)){ |
| k->ref++; |
| freeattr(a); |
| return k; |
| } |
| } |
| freeattr(a); |
| werrstr("no key found"); |
| return nil; |
| } |
| |
| Key* |
| keyfetch(Conv *c, char *fmt, ...) |
| { |
| int i, tag; |
| Attr *a; |
| Key *k; |
| va_list arg; |
| |
| va_start(arg, fmt); |
| a = parseattrfmtv(fmt, arg); |
| va_end(arg); |
| |
| flog("keyfetch %A", a); |
| tag = 0; |
| |
| for(i=0; i<ring.nkey; i++){ |
| k = ring.key[i]; |
| if(tag < k->tag) |
| tag = k->tag; |
| if(matchattr(a, k->attr, k->privattr)){ |
| k->ref++; |
| if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){ |
| k->ref--; |
| continue; |
| } |
| freeattr(a); |
| flog("using key %A %N", k->attr, k->privattr); |
| return k; |
| } |
| } |
| |
| if(needkey(c, a) < 0) |
| convneedkey(c, a); |
| |
| for(i=0; i<ring.nkey; i++){ |
| k = ring.key[i]; |
| if(k->tag <= tag) |
| continue; |
| if(matchattr(a, k->attr, k->privattr)){ |
| k->ref++; |
| if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){ |
| k->ref--; |
| continue; |
| } |
| freeattr(a); |
| return k; |
| } |
| } |
| freeattr(a); |
| werrstr("no key found"); |
| return nil; |
| } |
| |
| static int taggen; |
| |
| void |
| keyadd(Key *k) |
| { |
| int i; |
| |
| k->ref++; |
| k->tag = ++taggen; |
| for(i=0; i<ring.nkey; i++){ |
| if(matchattr(k->attr, ring.key[i]->attr, nil) |
| && matchattr(ring.key[i]->attr, k->attr, nil)){ |
| keyclose(ring.key[i]); |
| ring.key[i] = k; |
| return; |
| } |
| } |
| |
| ring.key = erealloc(ring.key, (ring.nkey+1)*sizeof(ring.key[0])); |
| ring.key[ring.nkey++] = k; |
| } |
| |
| void |
| keyclose(Key *k) |
| { |
| if(k == nil) |
| return; |
| |
| if(--k->ref > 0) |
| return; |
| |
| if(k->proto->closekey) |
| (*k->proto->closekey)(k); |
| |
| freeattr(k->attr); |
| freeattr(k->privattr); |
| free(k); |
| } |
| |
| Key* |
| keyreplace(Conv *c, Key *k, char *fmt, ...) |
| { |
| Key *kk; |
| char *msg; |
| Attr *a, *b, *bp; |
| va_list arg; |
| |
| va_start(arg, fmt); |
| msg = vsmprint(fmt, arg); |
| if(msg == nil) |
| sysfatal("out of memory"); |
| va_end(arg); |
| |
| /* replace prompted values with prompts */ |
| a = copyattr(k->attr); |
| bp = parseattr(k->proto->keyprompt); |
| for(b=bp; b; b=b->next){ |
| a = delattr(a, b->name); |
| a = addattr(a, "%q?", b->name); |
| } |
| freeattr(bp); |
| |
| if(badkey(c, k, msg, a) < 0) |
| convbadkey(c, k, msg, a); |
| kk = keylookup("%A", a); |
| freeattr(a); |
| keyclose(k); |
| if(kk == k){ |
| keyclose(kk); |
| werrstr("%s", msg); |
| return nil; |
| } |
| |
| if(strfindattr(kk->attr, "confirm")){ |
| if(confirmkey(c, kk) != 1){ |
| werrstr("key use not confirmed"); |
| keyclose(kk); |
| return nil; |
| } |
| } |
| return kk; |
| } |
| |
| void |
| keyevict(Conv *c, Key *k, char *fmt, ...) |
| { |
| char *msg; |
| Attr *a, *b, *bp; |
| va_list arg; |
| |
| va_start(arg, fmt); |
| msg = vsmprint(fmt, arg); |
| if(msg == nil) |
| sysfatal("out of memory"); |
| va_end(arg); |
| |
| /* replace prompted values with prompts */ |
| a = copyattr(k->attr); |
| bp = parseattr(k->proto->keyprompt); |
| for(b=bp; b; b=b->next){ |
| a = delattr(a, b->name); |
| a = addattr(a, "%q?", b->name); |
| } |
| freeattr(bp); |
| |
| if(badkey(c, k, msg, nil) < 0) |
| convbadkey(c, k, msg, nil); |
| keyclose(k); |
| } |