# rhentry -- entry combo widgets
# Copyright (C) 1996, 1997 Red Hat Software, Inc
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


import string
import crypt
import rand

from Tkinter import *
from rhtkinter import *
from buttonbar import *
from foldertabs import *
from rhutil import *
from rhdialog import Dialog
from textbox import *
from listbox import *
from Conf import *

import rhdialog
import os
from sys import exit
import posixpath
import regex
import regsub
import glob


class LabelledEntry(RHFrame):
    def bind(self, key, action):
	self.E.bind(key, action)
    def focus_set(self):
	self.E.focus_set()
    def __init__(self, Master, text, textvar, width):
	RHFrame.__init__(self, Master)
	self.L = Label(self, {'text':text, 'width':width, 'anchor':'w'})
	self.E = Entry(self, {'textvar':textvar})
	self.L.pack({'side':'left'})
	self.E.pack({'side':'left', 'expand':'1', 'fill':'x'})

# Label stacked above Entry
class LabelledStackEntry(LabelledEntry):
    def __init__(self, Master, text, textvar, width):
	RHFrame.__init__(self, Master)
	self.L = Label(self, {'text':text, 'anchor':'w'})
	self.E = Entry(self, {'textvar':textvar, 'width':width})
	self.L.pack({'side':'top'})
	self.E.pack({'side':'left', 'expand':'1', 'fill':'x'})


class PasswordEntry(LabelledEntry):
    def configure(self, cnf={}):
	self.L.configure(cnf)
    def __init__(self, Master, text, textvar, width):
	RHFrame.__init__(self, Master)
	self.L = Label(self, {'text':text, 'width':width, 'anchor':'w'})
	self.E = Entry(self, {'show':'*', 'textvar':textvar})
	self.L.pack({'side':'left'})
	self.E.pack({'side':'left', 'expand':'1', 'fill':'x'})


class LabelledLabel(RHFrame):
    def focus_set(self):
	self.E.focus_set()
    def __init__(self, Master, text, vartext, width):
	RHFrame.__init__(self, Master)
	self.L = Label(self, {'text':text, 'width':width, 'anchor':'w'})
	self.E = Label(self, {'text':vartext, 'anchor':'w'})
	self.L.pack({'side':'left'})
	self.E.pack({'side':'left', 'expand':'1', 'fill':'x'})
    def settext(self, vartext):
	self.E.config({'text':vartext})

class LabelledMenu(RHFrame):
    def focus_set(self):
	self.MB.focus_set()
    def __init__(self, Master, text, textvar, width, menulist):
	# Menulist is a list of lists/tuples each with two elements:
	# [type, cnf]
	# type is the type of the item: command, cascade, checkbutton, etc.
	# cnf is a standard configuration dictionary.  It must include
	# command for commands, or whatever is appropriate for the type.
	dropdown = '@/usr/lib/rhs/control-panel/loopy/dropdown.xbm'
	RHFrame.__init__(self, Master)
	self.MF = Frame(self)
	self.L = Label(self.MF, {'text':text,
				 'width':str(string.atoi(width)-3),
				 'anchor':'w'})
	self.MB = Menubutton(self.MF, {'anchor':'e', 'bitmap':dropdown,
				       'width':'17', 'justify':'center',
				       'relief':'raised'})
	self.M = Menu(self.MB, {'tearoff':'0'})
	self.MB.configure({'menu':self.M})
	for item in menulist:
	    self.M.add(item[0], item[1])
	self.MB.pack({'side':'right'})
	self.L.pack({'side':'left'})

	self.MF.pack({'side':'left'})
	self.E = Entry(self, {'textvar':textvar})
	self.E.pack({'side':'left', 'expand':'1', 'fill':'x'})


class SetPassword:
    def __init__(self, Master=None):
	self.step = 0
	self.encrypted = ''
	self.L = Toplevel(Master)
	self.L.title('Set Password')
	F = RHFrame(self.L)
	self.password = StringVar(self.L)
	self.E = LabelledLabel(F, 'Encrypted Password:', '', '20')
	self.E.pack({'side':'top', 'expand':'1', 'fill':'x'})
	self.P = PasswordEntry(F, 'Password:', self.password, '20')
	self.P.pack({'side':'top', 'expand':'1', 'fill':'x'})
	self.P.bind('<Return>', self.enterHit)
	self.P.focus_set()
	self.BB = ButtonBar(F)
	self.BB.setOrientation('horizontal')
	self.BB.addButton('Done', lambda x=self:not x.get() or x.L.destroy())
	self.BB.addButton('Cancel', lambda x=self:x.set('') or x.L.destroy())
	self.BB.pack({'side':'bottom'})
	F.pack({'side':'top', 'expand':'1', 'fill':'both'})
	self.L.update()
	self.L.grab_set()
	self.L.wait_window(self.L)
	self.L.grab_release()
    def enterHit(self, event=None):
	if self.step == 1:
	    if cmp(self.firstpass, self.password.get()):
		# passwords typed were not the same
		Dialog('Warning',
                  'Two different passwords were entered.\nPlease try again.',
                  'warning', 0, ['Retry'])
	    else:
		self.encrypted = crypt.crypt(self.password.get(), self.mksalt())
		self.E.settext(self.encrypted)
		self.BB.focus_set()
	    # Start over if they want to...
	    self.password.set('')
	    self.P.configure({'text':'Password:'})
	    self.step = 0
	    return
	if self.step == 0:
	    self.encrypted = ''
	    self.E.settext(self.encrypted)
	    self.firstpass = self.password.get()
	    self.password.set('')
	    self.P.configure({'text':'Verify:'})
	    self.step = 1
    def get(self):
	return self.encrypted
    def set(self, val):
	self.encrypted = val
    def mksalt(self):
	ret = ['','']
	for i in [0,1]:
	    j = rand.choice(range(0,64))
	    if (j < 26):
		ret[i] = string.lowercase[j]
	    elif (j < 52):
		ret[i] = string.uppercase[j-26]
	    elif (j < 62):
		ret[i] = string.digits[j-52]
	    elif (j == 63):
		ret[i] = '.'
	    else:
		ret[i] = '/'
	return ret[0]+ret[1]

class ChatBox(Frame):
    def __init__(self, Master, titles=['Expect', 'Send']):
	Frame.__init__(self, Master, {'relief':'groove', 'bd':'3'})
	self.CB = MultifieldListbox(self, [(titles[0], 30, 1),
					   (titles[1], 30, 1)])
	self.CB.bind('<Double-Button-1>', self.editEntry)
	self.BB = ButtonBar(self)
	self.BB.setOrientation('horizontal')
	self.BB.addButton('Insert', self.insertEntry)
	self.BB.addButton('Append', self.appendEntry)
	self.BB.addButton('Edit', self.editEntry)
	self.BB.addButton('Remove', self.removeEntry)
	self.BB.pack({'side':'bottom'})
	self.CB.pack({'side':'top', 'expand':'yes', 'fill':'both'})
    def insert(self, list):
	self.CB.insert(list)
    def getlist(self):
	return self.CB.getAllItems()
    def insertEntry(self):
	if not self.CB.getSelectedItems():
	    return
	index = string.atoi(self.CB.curselection()[0])
	self.edit()
	if self.list:
	    # not cancelled
	    self.CB.insert(self.list, index)
	    self.CB.selectLine(index)
    def appendEntry(self):
	self.edit()
	if self.list:
	    # not cancelled
	    self.CB.insert(self.list, 'end')
	    self.CB.selectLine('end')
    def editEntry(self, event=None):
	if not self.CB.getSelectedItems():
	    return
	index = string.atoi(self.CB.curselection()[0])
	self.edit(index)
	if self.list:
	    # not cancelled
	    self.CB.delete(index)
	    self.CB.insert(self.list)
	    self.CB.selectLine(index)
    def removeEntry(self):
	if not self.CB.getSelectedItems():
	    return
	index = string.atoi(self.CB.curselection()[0])
	self.CB.delete(index)
	self.CB.selectLine(index)
    def edit(self, index = -1):
	self.list = []
	self.saveindex = index
	self.T = Toplevel()
	self.T.title('Edit Chat Entry')
	self.expect = StringVar(self.T)
	self.send = StringVar(self.T)
	if index >= 0:
	    (expect, send) = self.CB.getItems(index)
	else:
	    (expect, send) = ('', '')
	self.expect.set(expect)
	self.send.set(send)
	F = RHFrame(self.T)
	LabelledEntry(F, 'Expect:', self.expect, '12').pack(
	  {'side':'top', 'expand':'1', 'fill':'x'})
	LabelledEntry(F, 'Send:', self.send, '12').pack(
	  {'side':'top', 'expand':'1', 'fill':'x'})
	BB = ButtonBar(F)
	BB.setOrientation('horizontal')
	BB.addButton('Done', self.set)
	BB.addButton('Cancel', self.T.destroy)
	BB.pack({'side':'bottom'})
	F.pack({'side':'top', 'expand':'1', 'fill':'both'})
	self.T.update()
	self.T.grab_set()
	self.T.wait_window(self.T)
	self.T.grab_release()
    def set(self):
	# set self.list
	self.list = [self.expect.get(), self.send.get()]
	self.T.destroy()


class EntryBox:
    def __init__(self, title, displaystring, Master=None):
	self.step = 0
	self.encrypted = ''
	self.L = Toplevel(Master)
	self.L.title(title)
	F = RHFrame(self.L)
	self.entry = StringVar(self.L)
	self.E = LabelledEntry(F, displaystring, self.entry, '20')
	self.E.pack({'side':'top', 'expand':'1', 'fill':'x'})
	self.E.bind('<Return>', lambda x=self:not x.get() or x.L.destroy())
	self.E.focus_set()
	self.BB = ButtonBar(F)
	self.BB.setOrientation('horizontal')
	self.BB.addButton('Done', lambda x=self:not x.get() or x.L.destroy())
	self.BB.addButton('Cancel', lambda x=self:x.set('') or x.L.destroy())
	self.BB.pack({'side':'bottom'})
	F.pack({'side':'top', 'expand':'1', 'fill':'both'})
	self.L.update()
	self.L.grab_set()
	self.L.wait_window(self.L)
	self.L.grab_release()
    def enterHit(self, event=None):
	if self.entry.get():
	    self.L.destroy()
    def get(self):
	return self.entry.get()
    def set(self, value):
	self.entry.set(value)

